JavaScript 非同步呼叫,javascript非同步呼叫
問題
可修改下面的 aa() 函數,目的是在一抄後用 console.log() 輸出 want-value
function aa() { setTimeout(function() { return "want-value"; }, 1000);}
但是,有其他需求:
aa() 函數可以隨意修改,但是不能有 console.log()
執行 console.log() 語句裡不能有 setTimeout 包裹
解答
也許這是個面試題,管它呢。問題的主要目的是考察對非同步呼叫執行結果的處理,既然是非同步呼叫,那麼 不可能同步等待非同步結果,結果一定是非同步
setTimeout() 經常用來類比非同步作業。最早,非同步是通過回調來通知(調用)處理常式處理結果的
function aa(callback) { setTimeout(function() { if (typeof callback === "function") { callback("want-value"); } }, 1000);}aa(function(v) { console.log(v);});
不過回調在用於稍大型一點的非同步應用時,容易出現多層嵌套,所以之後提出了一些對其進行“扁平”化,這一部分可以參考閑談非同步呼叫“扁平”化。當然 Promise 是非常流行的一種方法,並最終被 ES6 採納。用Promise 實現如下:
function aa() { return new Promise(resolve => { setTimeout(function() { resolve("want-value"); }, 1000); });}aa().then(v => console.log(v));
就這個例子來說,它和前面回調的例子大同小異。不過它會引出目前更推薦的一種方法——async/await,從 ES2017 開始支援:
function aa() { return new Promise(resolve => { setTimeout(function() { resolve("want-value"); }, 1000); });}async function main() { const v = await aa(); console.log(v);}main();
aa() 的定義與 Promise 方法中的定義是一樣的,但是在調用的時候,使用了 await ,非同步等待,等待到非同步結果之後,再使用 console.log() 對其進行處理。
這裡需要注意的是 await 只能在 async 方法中使用,所以為了使用 await 必須定義一個 async 的 main 方法,並在全域範圍中調用。由於 main 方法是非同步(申明為 async),所以如果 main() 調用之後還有其它語句,比如 console.log("hello") ,那麼這一句話會先執行。
async/await 文法讓非同步呼叫寫起來像寫同步代碼,在編寫代碼的時候,可以避免邏輯跳躍,寫起來會更輕鬆。(參考: 從地獄到天堂,Node 回調向 async/await 轉變 )
當然,定義 main() 再調用 main() 這部分可以用 IIFE 封裝一下,
(async () => { const v = await aa(); console.log(v);})();
總結
以上所述是小編給大家介紹的JavaScript 非同步呼叫,希望對大家有所協助,如果大家有任何疑問請給我留言,小編會及時回複大家的。在此也非常感謝大家對幫客之家網站的支援!