來自推特上 Windows 故障分析的笑話 圖片來源:me.me
推上看到的笑話,Windows 故障分析的實現。
然后想起來 JavaScript 中如何實現這個 sleep()
函數讓代碼暫停指定時間。
異步版本
借助 Promise 這事很好實現。
function sleep(time) {
return new Promise(resolve => {
setTimeout(() => {
resolve();
}, time);
});
}
創建一個 Promise
,等待指定時間后 resolve 掉即可。
但,Promise
是異步的,它要求后續代碼要么包含在 then
里面,要么通過 async/await
來調用。
所以使用起來應該像這樣子,
function testSleep() {
console.log("will sleep for 1s");
sleep(1000).then(() => {
console.log("will sleep for another 5s");
sleep(5000).then(() => {
console.log("waked up");
});
});
}
testSleep();
或者這樣子:
async function testSleep() {
console.log("will sleep for 1s");
await sleep(1000);
console.log("will sleep for another 5s");
await sleep(5000);
console.log("waked up");
}
testSleep();
測試 sleep
當然后者會更加優雅些,但本質上都是需要保證后續代碼在 Promise 回調中執行。如何有回調之外的代碼,則不會被阻斷,這便是其缺點。
async function testSleep() {
console.log("will sleep for 1s");
await sleep(1000);
console.log("will sleep for another 5s");
await sleep(5000);
console.log("waked up");
}
testSleep();
// 🚨不會按預期那樣最后執行,而是立即被執行
console.log("我在等上面的代碼執行完...");
代碼未阻斷的情況
同步版本
不借助異步異步代碼想阻斷代碼執行,那其實可以讓代碼原地跑,通過 while
。
function syncSleep(time) {
const start = new Date().getTime();
while (new Date().getTime() - start < time) {}
}
使用起來就和正常函數沒區別了,對周圍代碼也沒有要求必需得在回調什么的:
console.log("start test sync sleep...");
syncSleep(3000);
console.log("sync sleep after 3s");
測試同步版本的 sleep
方便是方便,但不建議使用這種方式,畢竟代碼在空跑。如果需要這樣的場景,你需要考慮是否可以修改下代碼或換個設計,異步能滿足大部分需求。