[英]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.