問題
原題來自 @若澤[wangwenlin] 的提問。
可修改下面的
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()
對其進行處理。
(async () => {
const v = await aa();
console.log(v);
})();