javascript 使用sleep函數(shù)的常見(jiàn)方法詳解
本文實(shí)例講述了javascript 使用sleep函數(shù)的常見(jiàn)方法。分享給大家供大家參考,具體如下:
一.什么是sleep函數(shù)?
花一點(diǎn)時(shí)間來(lái)聊一下sleep函數(shù),首先什么是sleep函數(shù)?
sleep是一種函數(shù),他的作用是使程序暫停指定的時(shí)間,起到延時(shí)的效果。
例如:
console.log('1'); sleep(5000); console.log('2');
控制臺(tái)輸出數(shù)字1后會(huì)間隔5秒后輸出數(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(function(){ console.log('1') setTimeout(function(){ console.log('2'); setTimeout(function(){ console.log('3'); console.timeEnd('runTime:'); }, 2000); }, 3000); }, 2000); // 1 // 2 // 3 // runTime:: 7013.104ms
上面的方式存在回調(diào)嵌套的問(wèn)題,我們希望有一個(gè)優(yōu)雅的方式來(lái)實(shí)現(xiàn)上面的例子:
sleep(2000); console.log('1'); sleep(3000); console.log('2'); sleep(2000); console.log('3'); ...
三.實(shí)現(xiàn)sleep
接下來(lái)我們就分別用幾種不同的方法來(lái)實(shí)現(xiàn)下sleep方法
1.基于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ù)
2.基于Promise的sleep
為了解決ajax的回調(diào)嵌套問(wèn)題,在jQuery1.8之后支持了Promise。但是單純的Promise只是將之前的縱向嵌套改為了橫向嵌套,
最終結(jié)果是下面的代碼:
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)改寫上面的例子
3.基于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í)行器的引用,所以還是有瑕疵。
當(dāng)然這不是最終版,因?yàn)镋S7為我們帶來(lái)了新的解決方案。
4.基于async函數(shù)的sleep
ES7新增了async函數(shù),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
效果和之前的一樣。
5.使用child_process(子進(jìn)程)實(shí)現(xiàn)sleep函數(shù)
前面介紹了幾種比較簡(jiǎn)單的sleep實(shí)現(xiàn),接下來(lái)看一個(gè)比較難的實(shí)現(xiàn)。
原理是將sleep放在子進(jìn)程中執(zhí)行,不會(huì)影響其他進(jìn)程,看代碼:
var childProcess = require('child_process'); var nodeBin = process.argv[0]; function sleep(time) { childProcess.execFileSync(nodeBin, ['-e', 'setTimeout(function() {}, ' + time + ');']); // childProcess.spawnSync(nodeBin, ['-e', 'setTimeout(function() {}, ' + time + ');']); } console.time('runTime:'); console.log('1'); sleep(1000); console.log('2'); sleep(2000); console.log('3'); console.timeEnd('runTime:'); // 1 // 2 // 3 // runTime:: 3579.093ms
以上代碼,是通過(guò)childProcess對(duì)象的execFileSync或者spawnSync創(chuàng)建一個(gè)同步進(jìn)程,
在同步進(jìn)程中執(zhí)行定時(shí)器,定時(shí)器執(zhí)行完畢后回收進(jìn)程,程序繼續(xù)執(zhí)行。
6.使用npm sleep包
前面的內(nèi)容都是我們自己實(shí)現(xiàn)的,其實(shí)npm上已經(jīng)有很多相關(guān)的js包了。
我們來(lái)看看他們是怎么實(shí)現(xiàn)的,sleep
var sleep = require('sleep'); console.log('1'); console.time('runTime:'); sleep.sleep(2); //休眠2秒鐘 console.log('2'); sleep.msleep(1000); //休眠1000毫秒 console.log('3'); sleep.usleep(1000000) //休眠1000000微秒 = 1秒 console.log('4'); console.timeEnd('runTime:'); // 1 // 2 // 3 // 4 // runTime:: 4014.455ms
很強(qiáng)有沒(méi)有,sleep包是C++編寫,然后擴(kuò)展到Node來(lái)實(shí)現(xiàn)sleep函數(shù)
也是一個(gè)不錯(cuò)的選擇。
以上就是sleep的六種簡(jiǎn)單實(shí)現(xiàn)。歡迎大家指出問(wèn)題,我們一起進(jìn)步。
感興趣的朋友可以使用在線HTML/CSS/JavaScript代碼運(yùn)行工具:http://tools.jb51.net/code/HtmlJsRun測(cè)試上述代碼運(yùn)行效果。
更多關(guān)于JavaScript相關(guān)內(nèi)容可查看本站專題:《JavaScript常用函數(shù)技巧匯總》、《javascript面向?qū)ο笕腴T教程》、《JavaScript錯(cuò)誤與調(diào)試技巧總結(jié)》、《JavaScript數(shù)據(jù)結(jié)構(gòu)與算法技巧總結(jié)》及《JavaScript數(shù)學(xué)運(yùn)算用法總結(jié)》
希望本文所述對(duì)大家JavaScript程序設(shè)計(jì)有所幫助。
相關(guān)文章
微信小程序獲取手機(jī)系統(tǒng)信息的方法【附源碼下載】
這篇文章主要介紹了微信小程序獲取手機(jī)系統(tǒng)信息的方法,涉及微信小程序wx.getSystemInfo函數(shù)的簡(jiǎn)單使用技巧,并附帶源碼供讀者下載參考,需要的朋友可以參考下2017-12-12簡(jiǎn)單了解Javscript中兄弟ifream的方法調(diào)用
這篇文章主要介紹了簡(jiǎn)單了解Javscript中兄弟ifream的方法調(diào)用文中通過(guò)示例代碼介紹的非常詳細(xì),對(duì)大家的學(xué)習(xí)或者工作具有一定的參考學(xué)習(xí)價(jià)值,,需要的朋友可以參考下2019-06-06用javascript實(shí)現(xiàn)頁(yè)內(nèi)搜索的腳本代碼
用javascript實(shí)現(xiàn)頁(yè)內(nèi)搜索的腳本代碼...2007-08-08JS實(shí)現(xiàn)玩轉(zhuǎn)風(fēng)車
這篇文章主要為大家詳細(xì)介紹了JS實(shí)現(xiàn)玩轉(zhuǎn)風(fēng)車,文中示例代碼介紹的非常詳細(xì),具有一定的參考價(jià)值,感興趣的小伙伴們可以參考一下2022-02-02淺談js繼承的實(shí)現(xiàn)及公有、私有、靜態(tài)方法的書寫
下面小編就為大家?guī)?lái)一篇淺談js繼承的實(shí)現(xiàn)及公有、私有、靜態(tài)方法的書寫。小編覺(jué)得挺不錯(cuò)的,現(xiàn)在就分享給大家,也給大家做個(gè)參考。一起跟隨小編過(guò)來(lái)看看吧2016-10-10js 阻止子元素響應(yīng)父元素的onmouseout事件具體實(shí)現(xiàn)
本文為大家介紹下js阻止子元素響應(yīng)父元素的onmouseout事件,具體實(shí)現(xiàn)如下,感興趣的朋友可以參考下2013-12-12MATLAB中fillmissing函數(shù)用法小結(jié)
這篇文章主要介紹了MATLAB中fillmissing函數(shù)用法,本文通過(guò)實(shí)例代碼給大家介紹的非常詳細(xì),對(duì)大家的學(xué)習(xí)或工作具有一定的參考借鑒價(jià)值,需要的朋友可以參考下2023-09-09uniapp實(shí)現(xiàn)微信H5掃碼功能的完整步驟
在uni-app官網(wǎng)上發(fā)現(xiàn)uni-app不支持H5掃碼功能,但是下面的提示說(shuō)明可以通過(guò)微信的JS-SDK實(shí)現(xiàn)掃碼功能,下面這篇文章主要給大家介紹了關(guān)于uniapp實(shí)現(xiàn)微信H5掃碼功能的完整步驟,需要的朋友可以參考下2022-11-11原生JS實(shí)現(xiàn)$.param() 函數(shù)的方法
這篇文章主要介紹了原生JS實(shí)現(xiàn)$.param() 函數(shù)的方法,由于遇到相關(guān)序列化的問(wèn)題,但是vue項(xiàng)目中由于減少隊(duì)jquery引用的限制,導(dǎo)致不能用$.param來(lái)序列化參數(shù),下面小編給大家分享了實(shí)例代碼,需要的朋友參考下吧2018-08-08