JavaScript實(shí)現(xiàn)sleep睡眠函數(shù)的幾種簡(jiǎn)單方法總結(jié)
一.什么是sleep函數(shù)?
sleep是一種函數(shù),他的作用是使程序暫停指定的時(shí)間,起到延時(shí)的效果。
官方介紹:sleep是一種函數(shù),作用是延時(shí),程序暫停若干時(shí)間,在執(zhí)行時(shí)要拋出一個(gè)中斷異常,必須對(duì)其進(jìn)行捕獲并處理才可以使用這個(gè)函數(shù)。
例如:
console.log('1'); sleep(2000); console.log('2');
控制臺(tái)輸出數(shù)字1后 會(huì)間隔2秒后輸出數(shù)字2
當(dāng)然上面的代碼是不能執(zhí)行的,因?yàn)閖s中是沒(méi)有sleep方法的。
所以這一篇文章主要介紹幾種在js中實(shí)現(xiàn)sleep的方式。
二.為什么使用sleep?
看到這里有人會(huì)問(wèn)了,為什么要使用sleep,上面的例子我可以使用setTimeout來(lái)實(shí)現(xiàn)???
因?yàn)閟etTimeout是通過(guò)回調(diào)函數(shù)來(lái)實(shí)現(xiàn)定時(shí)任務(wù)的,所以在多任務(wù)的場(chǎng)景下就會(huì)出現(xiàn)回調(diào)嵌套:
console.time('runTime:'); setTimeout(() => { console.log('1'); setTimeout(() => { console.log('2') setTimeout(() => { console.log('3') console.timeEnd('runTime:'); }, 2000); }, 3000); }, 2000); //結(jié)果: //1 //2 //3 //runTime:: 7017.87890625 ms
上面的方式存在回調(diào)嵌套的問(wèn)題,我們希望可以利用sleep函數(shù)更方便優(yōu)雅地實(shí)現(xiàn)上面的例子。
三.實(shí)現(xiàn)sleep
接下來(lái)我們就分別用幾種不同的方法來(lái)實(shí)現(xiàn)下sleep方法:
基于Date實(shí)現(xiàn)
通過(guò)死循環(huán)來(lái)阻止代碼執(zhí)行,同時(shí)不停比對(duì)是否超時(shí)。
function sleep(time){ var timeStamp = new Date().getTime(); var endTime = timeStamp + time; while(true){ if (new Date().getTime() > endTime){ return; } } } console.time('runTime:'); sleep(2000); console.log('1'); sleep(3000); console.log('2'); sleep(2000); console.log('3'); console.timeEnd('runTime:'); // 1 // 2 // 3 // runTime:: 7004.301ms
缺點(diǎn):
以上的代碼不會(huì)讓線程休眠,而是通過(guò)高負(fù)荷計(jì)算使cpu無(wú)暇處理其他任務(wù)。
這樣做的缺點(diǎn)是在sleep的過(guò)程中其他所有的任務(wù)都會(huì)被暫停,包括dom的渲染。
所以sleep的過(guò)程中程序會(huì)處于假死狀態(tài),并不會(huì)去執(zhí)行其他任務(wù)
基于Promise的sleep
單純的Promise只是將之前的縱向嵌套改為了橫向嵌套:
function sleep(time){ return new Promise(function(resolve){ setTimeout(resolve, time); }); } console.time('runTime:'); console.log('1'); sleep(1000).then(function(){ console.log('2'); sleep(2000).then(function(){ console.log('3'); console.timeEnd('runTime:'); }); }); console.log('a'); // 1 // a // 2 // 3 // runTime:: 3013.476ms
這其實(shí)和之前的setTimeout嵌套沒(méi)什么區(qū)別,也很難看。
我們?cè)俅芜M(jìn)行優(yōu)化,使用ES6的Generator函數(shù)來(lái)改寫上面的例子
基于Generator函數(shù)的sleep
我們對(duì)sleep的執(zhí)行使用Generator函數(shù)來(lái)執(zhí)行,并且搭配co來(lái)進(jìn)行自執(zhí)行。
var co = require('co'); function sleep(time){ return new Promise(function(resolve){ setTimeout(resolve, time); }); } var run = function* (){ console.time('runTime:'); console.log('1'); yield sleep(2000); console.log('2'); yield sleep(1000); console.log('3'); console.timeEnd('runTime:'); } co(run); console.log('a'); // 1 // a // 2 // 3 // runTime:: 3004.935ms
可以看到整體的代碼看起來(lái)不存在嵌套的關(guān)系,并且執(zhí)行過(guò)程不會(huì)發(fā)生假死情況,不會(huì)阻塞其他任務(wù)的執(zhí)行。
但是多了一個(gè)co執(zhí)行器的引用,所以還是有瑕疵。
基于async函數(shù)的sleep
async函數(shù)最大的特點(diǎn)就是自帶執(zhí)行器,所以我們可以不借助co來(lái)實(shí)現(xiàn)sleep了
function sleep(time){ return new Promise((resolve) => setTimeout(resolve, time)); } async function run(){ console.time('runTime:'); console.log('1'); await sleep(2000); console.log('2'); await sleep(1000); console.log('3'); console.timeEnd('runTime:'); } run(); console.log('a'); // 1 // a // 2 // 3 // runTime:: 3009.984ms
附:還有一種死循環(huán)寫法(參考自網(wǎng)絡(luò))
思路是利用系統(tǒng)時(shí)間,一旦沒(méi)有運(yùn)行到自己設(shè)定的時(shí)間就讓程序一直在循環(huán)里計(jì)算(個(gè)人感覺(jué)實(shí)現(xiàn)簡(jiǎn)單,實(shí)際運(yùn)行可能有點(diǎn)恐怖)
function sleep(numberMillis) { //記錄當(dāng)前時(shí)間 var now = new Date(); //設(shè)置未來(lái)的某個(gè)時(shí)間 var exitTime = now.getTime() + numberMillis; while (true) { //獲取當(dāng)前時(shí)間 now = new Date(); //檢查是否到了設(shè)置好的未來(lái)時(shí)間 if (now.getTime() > exitTime) return; } }
總結(jié)
到此這篇關(guān)于JavaScript實(shí)現(xiàn)sleep睡眠函數(shù)的幾種簡(jiǎn)單方法總結(jié)的文章就介紹到這了,更多相關(guān)JS實(shí)現(xiàn)sleep睡眠函數(shù)內(nèi)容請(qǐng)搜索腳本之家以前的文章或繼續(xù)瀏覽下面的相關(guān)文章希望大家以后多多支持腳本之家!
相關(guān)文章
javascript實(shí)現(xiàn)獲取指定精度的上傳文件的大小簡(jiǎn)單實(shí)例
下面小編就為大家?guī)?lái)一篇javascript實(shí)現(xiàn)獲取指定精度的上傳文件的大小簡(jiǎn)單實(shí)例。小編覺(jué)得挺不錯(cuò)的,現(xiàn)在就分享給大家,也給大家做個(gè)參考。一起跟隨小編過(guò)來(lái)看看吧2016-10-10JS基于遞歸實(shí)現(xiàn)網(wǎng)頁(yè)版計(jì)算器的方法分析
這篇文章主要介紹了JS基于遞歸實(shí)現(xiàn)網(wǎng)頁(yè)版計(jì)算器的方法,結(jié)合實(shí)例形式分析了javascript采用遞歸算法實(shí)現(xiàn)網(wǎng)頁(yè)版計(jì)算器的步驟與相關(guān)操作技巧,需要的朋友可以參考下2017-12-12js實(shí)現(xiàn)簡(jiǎn)單的點(diǎn)名器隨機(jī)色實(shí)例代碼
這篇文章主要給大家介紹了關(guān)于js實(shí)現(xiàn)簡(jiǎn)單的點(diǎn)名器隨機(jī)色的相關(guān)資料,文中通過(guò)示例代碼介紹的非常詳細(xì),對(duì)大家的學(xué)習(xí)或者工作具有一定的參考學(xué)習(xí)價(jià)值,需要的朋友們下面隨著小編來(lái)一起學(xué)習(xí)學(xué)習(xí)吧2020-09-09ES6中Set和Map數(shù)據(jù)結(jié)構(gòu),Map與其它數(shù)據(jù)結(jié)構(gòu)互相轉(zhuǎn)換操作實(shí)例詳解
這篇文章主要介紹了ES6中Set和Map數(shù)據(jù)結(jié)構(gòu),Map與其它數(shù)據(jù)結(jié)構(gòu)互相轉(zhuǎn)換操作,結(jié)合實(shí)例形式詳細(xì)分析了ES6中的Set和Map數(shù)據(jù)結(jié)構(gòu)的概念、原理、遍歷、去重等操作,以及Map與其它數(shù)據(jù)結(jié)構(gòu)互相轉(zhuǎn)換操作,需要的朋友可以參考下2019-02-02JavaScript判斷數(shù)組是否包含指定元素的方法
這篇文章主要介紹了JavaScript判斷數(shù)組是否包含指定元素的方法,涉及javascript中contains方法的使用技巧,需要的朋友可以參考下2015-07-07精彩的Bootstrap案例分享 重點(diǎn)在注釋!(選項(xiàng)卡、柵格布局)
這篇文章主要為大家分享了一個(gè)精彩的Bootstrap案例,涉及到了選項(xiàng)卡、柵格布局,關(guān)鍵重點(diǎn)在注釋,感興趣的小伙伴們可以參考一下2016-07-07JavaScript 通過(guò)模式匹配實(shí)現(xiàn)重載
昨天rank同學(xué)向我提出一個(gè)問(wèn)題,在實(shí)際應(yīng)用中有些接口需要提供類似于函數(shù)重載的功能,以方便開發(fā)者組織代碼邏輯,簡(jiǎn)化使用者調(diào)用。2010-08-08