国产成人精品久久免费动漫-国产成人精品天堂-国产成人精品区在线观看-国产成人精品日本-a级毛片无码免费真人-a级毛片毛片免费观看久潮喷

您的位置:首頁技術(shù)文章
文章詳情頁

js實現(xiàn)0ms延時定時器的幾種方式

瀏覽:113日期:2024-03-21 18:52:10
目錄queueMicrotaskasync/awaitMessageChannel最后附錄

這兩天看到一篇介紹《如何實現(xiàn)準(zhǔn)時的 setTimeout?》的文章,文章起源于一道面試題:有什么辦法讓setTimeout準(zhǔn)時呀?具體文章內(nèi)容可查看附錄【1】,看完之后,引起了我對setTimeout這個函數(shù)的探究興趣,因此在MDN上重新查閱了相關(guān)文檔,其中提到【最小延時 >=4ms】的一點,因此使用setTimeout不能實現(xiàn)0ms延時的定時器,如果要實現(xiàn)的話,提供了一個參考鏈接【2】,作者的實現(xiàn)思路是通過postMessage來模擬,繞過setTimeout的限制,從而實現(xiàn)0ms延時的定時器,說簡單來講就是起了一個宏任務(wù)去執(zhí)行回調(diào),先具體看下是怎么實現(xiàn)的:

(function() { var timeouts = []; var messageName = 'zero-timeout-message'; // Like setTimeout, but only takes a function argument. There’s // no time argument (always zero) and no arguments (you have to use a closure) function setZeroTimeout(fn) { timeouts.push(fn); window.postMessage(messageName, '*'); } function handleMessage(event) { if (event.source == window && event.data == messageName) { event.stopPropagation(); if (timeouts.length > 0) { var fn = timeouts.shift(); fn(); } } } window.addEventListener('message', handleMessage, true); // Add the one thing we want added to the window object. window.setZeroTimeout = setZeroTimeout;})();

作者還提供了一個demo頁面【3】,通過于setTimeout(0)進(jìn)行對比,在我瀏覽器的執(zhí)行結(jié)果如下:

100 iterations of setZeroTimeout took 15 milliseconds.100 iterations of setTimeout(0) took 488 milliseconds.

根據(jù)結(jié)果對比來看,setZeroTimeout執(zhí)行比setTimeout快了上百倍,這是一個巨大的提升。今天想討論的是除了上述這種方式,還可以通過哪些方式來實現(xiàn)一個0ms延時的定時器呢,首先,我們要確定一下我們自定義的定時器是異步的,其次是盡可能早的被執(zhí)行。說起異步,js提供了好幾種解決方案,我們可以逐一去驗證。

在深入討論各種實現(xiàn)方式之前,約定提供的setTimeout對比版本如下,后面自定義實現(xiàn)的方案都將和setTimeout版本的執(zhí)行時間進(jìn)行對比,代碼比較簡單:

(function() { let i = 0; const start = Date.now(); function test() { if(i++ < 100) { setTimeout(test); } else { console.log(’setTimeout執(zhí)行時間:’, Date.now() - start); } } setTimeout(test);})();queueMicrotask

queueMicrotask這個api可以添加一個微任務(wù),使用比較簡單,直接傳遞一個回調(diào)函數(shù)即可,具體實現(xiàn)如下:

(function() { function setZeroTimeout(fn) { queueMicrotask(fn); } let i = 0; const start = Date.now(); function test() { if(i++ < 100) { setZeroTimeout(test); } else { console.log(’setZeroTimeout執(zhí)行時間:’, Date.now() - start); } } setZeroTimeout(test);})();

通過和setTimeout版本進(jìn)行對比,最終結(jié)果如下:

setZeroTimeout執(zhí)行時間: 2setTimeout執(zhí)行時間: 490

關(guān)于這個API的介紹在MDN上有詳細(xì)的說明,就不展開介紹了,這里多說一點,根據(jù)規(guī)范文檔的說明,大多數(shù)情況下,推薦使用requestAnimationFrame()和requestIdleCallback()等api,因為queueMicrotask會阻塞渲染,在很多時候都不是一種好的實踐。

async/await

async/await對于前端開發(fā)人員來說已經(jīng)是必不可少的了,這里我們也可以用來實現(xiàn):

(function() { async function setAsyncTimeout(fn) { Promise.resolve().then(fn); } let i = 0; const start = Date.now(); async function test() { if (i++ < 100) { await setAsyncTimeout(test); } else { console.log(’setAsyncTimeout執(zhí)行時間:’, Date.now() - start); } } setAsyncTimeout(test);})();

通過和setTimeout版本進(jìn)行對比,最終結(jié)果如下:

setAsyncTimeout執(zhí)行時間: 2setTimeout執(zhí)行時間: 490

如果不嫌麻煩,還可以通過Promise來實現(xiàn),其實都是大同小異,無非多些點代碼,這里就省略了。

MessageChannel

MessageChannel允許我們創(chuàng)建一個新的消息通道,并通過它的兩個MessagePort屬性發(fā)送數(shù)據(jù),MessageChannel提供端口的概念,實現(xiàn)端口之間的通信,比如worker/iframe之間的通信。

(function() { const channel = new MessageChannel(); function setMessageChannelTimeout(fn) { channel.port2.postMessage(null); } channel.port1.onmessage = function() { test(); }; let i = 0; const start = Date.now(); function test() { if(i++ < 100) { setMessageChannelTimeout(test); } else { console.log(’setMessageChannelTimeout執(zhí)行時間:’, Date.now() - start); } } setMessageChannelTimeout(test);})();

通過和setTimeout版本進(jìn)行對比,最終結(jié)果如下:

setMessageChannelTimeout執(zhí)行時間: 4setTimeout執(zhí)行時間: 490

第三種方式運行時間比前面兩種更長些,因為通過MessageChannel產(chǎn)生的是宏任務(wù),其他兩種是微任務(wù),微任務(wù)執(zhí)行靠前,且會阻塞主線程,因此時間會長一點。

最后

本文提供了三種實現(xiàn)方式,都是圍繞js提供異步解決方案來實現(xiàn)的,實現(xiàn)本身并不復(fù)雜。

附錄

​​【1】https://mp.weixin.qq.com/s/QRIXBoKr2dMgLob3Atq9-g【2】https://dbaron.org/log/20100309-faster-timeouts【3】https://dbaron.org/mozilla/zero-timeout

到此這篇關(guān)于js實現(xiàn)0ms延時定時器的幾種方式的文章就介紹到這了,更多相關(guān)js 延時定時器 內(nèi)容請搜索好吧啦網(wǎng)以前的文章或繼續(xù)瀏覽下面的相關(guān)文章希望大家以后多多支持好吧啦網(wǎng)!

標(biāo)簽: JavaScript
相關(guān)文章:
主站蜘蛛池模板: 办公室紧身裙丝袜av在线 | 国内自拍小视频 | 三级全黄视频 | 国产末成年女噜噜片 | 精品三级国产一区二区三区四区 | 日韩精品欧美激情国产一区 | 久草在线视频免费看 | 国产亚洲精品一品区99热 | 亚洲精品美女 | 呦视频在线一区二区三区 | 人人爽人人香蕉 | 日韩区 | 九九99香蕉在线视频网站 | 国产精品久久久久激情影院 | 欧美成人高清免费大片观看 | 久草三级 | 特级a欧美做爰片毛片 | 一级毛片免费看 | 亚洲美女综合网 | 悠悠影院欧美日韩国产 | 欧美日韩亚洲综合在线一区二区 | 国产大陆亚洲精品国产 | 中文精品视频一区二区在线观看 | 精品久久久久久久久久中文字幕 | 亚洲色吧 | 日韩一区二区三区视频 | 欧美一区二区免费 | 手机福利片 | 日本毛片免费看 | 一区二区三区日本视频 | 成人久久免费视频 | 91视频站 | 网友自拍第一页 | 国产精品久久久久网站 | 欧美.成人.综合在线 | 成年片免费网址网站 | 欧美日韩亚洲视频 | 一个人看的www片免费视频中文 | 黄色作爱 | 视频一区在线 | 在线视频一区二区三区三区不卡 |