js 定時器筆試題 分析以下代碼實際啟動並執行結果:
for (var i = 0; i < 5; i++) { setTimeout(function() { console.log(new Date, i); }, 1000);}console.log(new Date, i);
JS 中同步和非同步代碼的區別、變數範圍、閉包等概念有正確的理解,就應該知道上面代碼的輸出結果:
Tue Mar 06 2018 10: 10: 26 GMT + 0800(中國標準時間) 5Tue Mar 06 2018 10: 10: 27 GMT + 0800(中國標準時間) 5Tue Mar 06 2018 10: 10: 27 GMT + 0800(中國標準時間) 5Tue Mar 06 2018 10: 10: 27 GMT + 0800(中國標準時間) 5Tue Mar 06 2018 10: 10: 27 GMT + 0800(中國標準時間) 5Tue Mar 06 2018 10: 10: 27 GMT + 0800(中國標準時間) 5
如果想間隔1s輸出一個數字,修改如下
for (var i = 0; i < 5; i++) { setTimeout(function() { console.log(new Date(), i) }, i * 1000) // 這裡的將上面的1000改為i*1000}console.log(new Date(), i);
輸出的結果如下
Tue Mar 06 2018 12:20:28 GMT+0800 (中國標準時間) 5Tue Mar 06 2018 12:20:28 GMT+0800 (中國標準時間) 5Tue Mar 06 2018 12:20:29 GMT+0800 (中國標準時間) 5Tue Mar 06 2018 12:20:30 GMT+0800 (中國標準時間) 5Tue Mar 06 2018 12:20:31 GMT+0800 (中國標準時間) 5Tue Mar 06 2018 12:20:32 GMT+0800 (中國標準時間) 5
如果想輸出不同的數字,則需要使用閉包,這裡使用自執行函數,也可以使用 let 代替 var 聲明 i
for (var i = 0; i < 5; i++) { (j => { setTimeout(function() { console.log(new Date, j) }, j * 1000) })(i) }console.log(new Date,i)
輸入結果如下
Tue Mar 06 2018 12:54:46 GMT+0800 (中國標準時間) 5Tue Mar 06 2018 12:54:46 GMT+0800 (中國標準時間) 0Tue Mar 06 2018 12:54:47 GMT+0800 (中國標準時間) 1Tue Mar 06 2018 12:54:48 GMT+0800 (中國標準時間) 2Tue Mar 06 2018 12:54:49 GMT+0800 (中國標準時間) 3Tue Mar 06 2018 12:54:50 GMT+0800 (中國標準時間) 4
使用Generator函數
Generator 函數是 ES6 提供的一種非同步編程解決方案.
for...of迴圈可以自動遍曆 Generator 函數時產生的Iterator對象,且此時不再需要調用next方法。
function* foo() { for (let i = 0; i < 5; i++) { yield i; } return 6;}for (let j of foo()) { setTimeout(() => { console.log(new Date, j) }, j * 1000)}
輸出如下
Tue Mar 06 2018 13:41:39 GMT+0800 (中國標準時間) 0Tue Mar 06 2018 13:41:40 GMT+0800 (中國標準時間) 1Tue Mar 06 2018 13:41:41 GMT+0800 (中國標準時間) 2Tue Mar 06 2018 13:41:42 GMT+0800 (中國標準時間) 3Tue Mar 06 2018 13:41:43 GMT+0800 (中國標準時間) 4
使用ES7中的async函數
async 函數就是將 Generator 函數的星號(*)替換成async,將yield替換成await,僅此而已。
async函數返回一個 Promise 對象,可以使用then方法添加回呼函數。當函數執行的時候,一旦遇到await就會先返回,等到非同步作業完成,再接著執行函數體內後面的語句。
// 類比其他語言中的 sleep,實際上可以是任何非同步作業const sleep = (timeountMS) => new Promise((resolve) => { setTimeout(resolve, timeountMS);});(async() => { // 聲明即執行的 async 函數運算式 for (var i = 0; i < 5; i++) { await sleep(1000); console.log(new Date, i); } await sleep(1000); console.log(new Date, i);})();
輸出如下
Tue Mar 06 2018 13:52:22 GMT+0800 (中國標準時間) 0Tue Mar 06 2018 13:52:23 GMT+0800 (中國標準時間) 1Tue Mar 06 2018 13:52:24 GMT+0800 (中國標準時間) 2Tue Mar 06 2018 13:52:25 GMT+0800 (中國標準時間) 3Tue Mar 06 2018 13:52:26 GMT+0800 (中國標準時間) 4Tue Mar 06 2018 13:52:27 GMT+0800 (中國標準時間) 5
使用 Promise
function delay(time) { return new Promise(function(resolve, reject) { setTimeout(resolve, time); })}for (let i = 0; i < 5; i++) { delay(i * 1000).then(() => console.log(new Date, i))}
輸出如下
Fri Mar 16 2018 09:57:04 GMT+0800 (中國標準時間) 0Fri Mar 16 2018 09:57:05 GMT+0800 (中國標準時間) 1Fri Mar 16 2018 09:57:06 GMT+0800 (中國標準時間) 2Fri Mar 16 2018 09:57:07 GMT+0800 (中國標準時間) 3Fri Mar 16 2018 09:57:08 GMT+0800 (中國標準時間) 4