您好,登錄后才能下訂單哦!
小編這次要給大家分享的是javascript如何使用sleep函數,文章內容豐富,感興趣的小伙伴可以來了解一下,希望大家閱讀完這篇文章之后能夠有所收獲。
一.什么是sleep函數?
花一點時間來聊一下sleep函數,首先什么是sleep函數?
sleep是一種函數,他的作用是使程序暫停指定的時間,起到延時的效果。
例如:
console.log('1'); sleep(5000); console.log('2');
控制臺輸出數字1后會間隔5秒后輸出數字2
當然上面的代碼是不能執行的,因為js中是沒有sleep方法的。
所以這一篇文章主要介紹幾種在js中實現sleep的方式。
二.為什么使用sleep?
看到這里有人會問了,為什么要使用sleep,上面的例子我可以使用setTimeout來實現啊?
因為setTimeout是通過回調函數來實現定時任務的,所以在多任務的場景下就會出現回調嵌套:
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
上面的方式存在回調嵌套的問題,我們希望有一個優雅的方式來實現上面的例子:
sleep(2000); console.log('1'); sleep(3000); console.log('2'); sleep(2000); console.log('3'); ...
三.實現sleep
接下來我們就分別用幾種不同的方法來實現下sleep方法
1.基于Date實現
通過死循環來阻止代碼執行,同時不停比對是否超時。
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
缺點:
以上的代碼不會讓線程休眠,而是通過高負荷計算使cpu無暇處理其他任務。
這樣做的缺點是在sleep的過程中其他所有的任務都會被暫停,包括dom的渲染。
所以sleep的過程中程序會處于假死狀態,并不會去執行其他任務
2.基于Promise的sleep
為了解決ajax的回調嵌套問題,在jQuery1.8之后支持了Promise。但是單純的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
這其實和之前的setTimeout嵌套沒什么區別,也很難看。
我們再次進行優化,使用ES6的Generator函數來改寫上面的例子
3.基于Generator函數的sleep
我們對sleep的執行使用Generator函數來執行,并且搭配co來進行自執行。
看代碼:
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
可以看到整體的代碼看起來不存在嵌套的關系,還是比較舒服的。
并且執行過程不會發生假死情況,不會阻塞其他任務的執行。
但是多了一個co執行器的引用,所以還是有瑕疵。
當然這不是最終版,因為ES7為我們帶來了新的解決方案。
4.基于async函數的sleep
ES7新增了async函數,async函數最大的特點就是自帶執行器,所以我們可以不借助co來實現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(子進程)實現sleep函數
前面介紹了幾種比較簡單的sleep實現,接下來看一個比較難的實現。
原理是將sleep放在子進程中執行,不會影響其他進程,看代碼:
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
以上代碼,是通過childProcess對象的execFileSync或者spawnSync創建一個同步進程,
在同步進程中執行定時器,定時器執行完畢后回收進程,程序繼續執行。
6.使用npm sleep包
前面的內容都是我們自己實現的,其實npm上已經有很多相關的js包了。
我們來看看他們是怎么實現的,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
很強有沒有,sleep包是C++編寫,然后擴展到Node來實現sleep函數
也是一個不錯的選擇。
看完這篇關于javascript如何使用sleep函數的文章,如果覺得文章內容寫得不錯的話,可以把它分享出去給更多人看到。
免責聲明:本站發布的內容(圖片、視頻和文字)以原創、轉載和分享為主,文章觀點不代表本網站立場,如果涉及侵權請聯系站長郵箱:is@yisu.com進行舉報,并提供相關證據,一經查實,將立刻刪除涉嫌侵權內容。