簡體   English   中英

什么時候應該在 typescript 中使用回調 function?

[英]When should I use callback function in typescript?

我曾經編寫過 C/C++ 代碼,我剛開始學習 TS。 讓我特別困惑的一件事是 TS 並不總是自上而下運行。 就像下面的例子一樣,它將打印“2 1”。

    function first(){
      // Simulate a code delay
      setTimeout( function(){
        console.log(1);
      }, 500 );
    }
    function second(){
      console.log(2);
    }
    first();
    second();

但是我怎么知道一個 function 是否可以足夠快地執行,以便程序可以自上而下的模式運行? 而且我可以想象,如果我在整個程序中繼續使用遞歸回調來模擬自上而下的模式,那將是一片混亂。

您需要學習基本的 javascript 以了解其工作原理。 有一種叫做“事件循環”的東西會導致這種行為。 簡而言之,setTimeout function 進入回調隊列,當棧內所有進程執行完畢后進入回調棧(進程從回調棧執行)。 你可以做一件有趣的事。 將時間設置為 0,看看會發生什么。

javascript 不是異步語言。 正是這個事件循環概念使 javascript 異步工作,但在幕后一切都像在 c/c++ 中一樣同步工作

Typescript 在編譯時被轉譯為 Javascript。 所以在運行時周圍沒有 Typescript,只有 Javascript。

Javascript引擎實現了兩個隊列:事件隊列和微任務隊列。 后者具有更高的優先級並被 Promises 使用。

考慮這段代碼及其打印輸出:

console.log('start');
setTimeout(function() {                               // queue to event queue                  
  console.log('timeout');
}, 0);
Promise.resolve().then(function() {                  // queue to microtask queue     
  console.log('promise1');
}).then(function() { console.log('promise2'); });    // queue to microtask queue
console.log('end');



start
end             // current call stack empty after printing so look at the queues
promise1        // dequeue and process a task from microtask queue
promise2        // keep doing the above ignoring the main event queue
timeout         // microtask queue empty so do dequeue and process an event from event queue

可以說,在 2019 年,您永遠不應該使用回調。 相反,您應該使用Promise

這允許開發人員選擇使用回調或使用更現代的 async/await

例子:

 function first() { // Simulate a code delay return new Promise((resolve) => { setTimeout(() => { console.log(1); resolve(); }, 500); }); } function second() { console.log(2); } (async() => { await first(); second(); })();

或者

 function first() { // Simulate a code delay return new Promise((resolve) => { setTimeout(() => { console.log(1); resolve(); }, 500); }); } function second() { console.log(2); } first().then(second);

我們也可以只包裝 setTimeout 本身

 function wait(ms = 0) { return new Promise(resolve => setTimeout(resolve, ms)); } async function first() { await wait(500); console.log(1); } function second() { console.log(2); } (async() => { await first(); second(); })();

再舉一個例子,說明使用 Promise 可以使 async/await 成為可能,這使您的代碼易於遵循,避免了您提到的嵌套地獄

 function wait(ms = 0) { return new Promise(resolve => setTimeout(resolve, ms)); } async function main() { await wait(1000); console.log('Each') await wait(1000); console.log('Of') await wait(1000); console.log('These'); await wait(1000); console.log('Messages'); await wait(1000); console.log('appears'); const words = ['one', 'second', 'after', 'the', 'previous'] for (const word of words) { await wait(1000); console.log(word); } } main();

此外,如果您不熟悉來自 C/C++ 的 JavaScript/TypeScript,您應該了解閉包,因為與 C/C++ 不同,沒有任何理由為回調提供userdata參數。

同樣正如@Sudip Sarker 提到的在事件循環中閱讀的那樣,JavaScript 是單線程的,並且在“事件循環”上運行。 並行運行的部分在瀏覽器本身和 API JavaScript 調用(加載圖像、調用獲取、等待超時等)。 JavaScript 本身一次只運行一個“事件”,然后退出等待下一個事件。

暫無
暫無

聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.

 
粵ICP備18138465號  © 2020-2024 STACKOOM.COM