欧美bbbwbbbw肥妇,免费乱码人妻系列日韩,一级黄片

詳解JavaScript如何實(shí)現(xiàn)更短時(shí)間的延時(shí)函數(shù)

 更新時(shí)間:2024年03月01日 15:15:18   作者:hktk_wb  
在項(xiàng)目開(kāi)發(fā)中,經(jīng)常能遇到需要延時(shí)執(zhí)行的需求,比如實(shí)現(xiàn)一個(gè)定時(shí)器功能,本文主要和大家介紹了JS如何實(shí)現(xiàn)更短時(shí)間的延時(shí)函數(shù),需要的可以參考下

在項(xiàng)目開(kāi)發(fā)中,經(jīng)常能遇到需要延時(shí)執(zhí)行的需求,比如實(shí)現(xiàn)一個(gè)定時(shí)器功能。

使用setTimeout實(shí)現(xiàn)延時(shí)函數(shù)

最常見(jiàn)的方式的就是使用setTimeout函數(shù)來(lái)實(shí)現(xiàn)了

// 延時(shí)
function sleep(time = 1000) {
    const promise = new Promise((resolve) => {
        setTimeout(() => {
            resolve(true);
        }, time);
    });

    return promise;
}

// 使用示例
async function run() {
    // do something
    // 延時(shí)2秒
    await sleep(2000);
    console.log("sleep end!");
    // do something
}

run();

延時(shí)精度測(cè)試

// 延時(shí)時(shí)間設(shè)置為`5ms`,循環(huán)執(zhí)行`1000`次,理論執(zhí)行時(shí)間為`5000ms`。
async function run() {
    console.time("run");
    for (let i = 0; i < 1000; i++) {
        await sleep(5);
    }
    console.timeEnd("run");
}

run();

// 以下為在瀏覽器console中的5次運(yùn)行結(jié)果(運(yùn)行結(jié)果在不同電腦配置下可能有出入)
// run: 5776.0888671875 ms
// run: 5775.033935546875 ms
// run: 5833.064208984375 ms
// run: 5804.203857421875 ms
// run: 5807.372802734375 ms

如上所示:這樣實(shí)現(xiàn)其實(shí)已經(jīng)可以滿足大部分需求了,但是總還會(huì)有一些特別的情況。

比如我想延時(shí)1毫秒,使用上面的方式就無(wú)能為力了,因?yàn)?code>setTimeout在瀏覽器的實(shí)現(xiàn)中限定了最小間隔時(shí)間為4ms,在設(shè)定小于這個(gè)時(shí)間時(shí),會(huì)默認(rèn)更改為4ms,因此這個(gè)延時(shí)函數(shù)理論上適用于4ms以上的延時(shí)情況。

那有沒(méi)有其他方式去實(shí)現(xiàn)更短時(shí)間的延時(shí)呢?

使用同步方式實(shí)現(xiàn)延時(shí)函數(shù)

后來(lái)想到不使用異步方式,而采用同步方式來(lái)實(shí)現(xiàn)延時(shí),使用循環(huán)來(lái)阻塞代碼執(zhí)行以達(dá)到延時(shí)的效果。

// 延時(shí)
function sleep(time = 1) {
    const start = performance.now();

    let delaying = true;
    while (delaying) {
        const end = performance.now();
        const delay = end - start;
        if (delay >= time) {
            delaying = false;
        }
    }
}

// 使用示例
async function run() {
    // do something
    // 延時(shí)1ms
    sleep(1);
    console.log("sleep end!");
    // do something
}

run();

延時(shí)精度測(cè)試

// 延時(shí)時(shí)間設(shè)置為`1ms`,循環(huán)執(zhí)行`1000`次,理論執(zhí)行時(shí)間為`1000ms`
function run() {
    console.time("run");
    for (let i = 0; i < 1000; i++) {
        sleep(1);
    }
    console.timeEnd("run");
}

run();

// 以下為在瀏覽器console中的5次運(yùn)行結(jié)果(運(yùn)行結(jié)果在不同電腦配置下可能有出入)
// run: 1000.179931640625 ms
// run: 1000.447998046875 ms
// run: 1000.274169921875 ms
// run: 1000.135009765625 ms
// run: 1000.19091796875 ms

// 延時(shí)時(shí)間設(shè)置為`0.1ms`,循環(huán)執(zhí)行`1000`次,理論執(zhí)行時(shí)間為`100ms`
function run2() {
    console.time("run");
    for (let i = 0; i < 1000; i++) {
        sleep(.1);
    }
    console.timeEnd("run");
}

// 以下為在瀏覽器console中的5次運(yùn)行結(jié)果(運(yùn)行結(jié)果在不同電腦配置下可能有出入)
// run: 167.093017578125 ms
// run: 166.85302734375 ms
// run: 167.038818359375 ms
// run: 166.60498046875 ms
// run: 167.81787109375 ms

可以看出,如果使用同步方法做延時(shí),精確度和最小延時(shí)時(shí)間都有突破性提高。

但是用此方式有一個(gè)極大的弊端,阻塞代碼運(yùn)行及瀏覽器渲染。因?yàn)?code>js為單線程運(yùn)行,以同步方式做延時(shí)就會(huì)導(dǎo)致其他代碼執(zhí)行阻塞,瀏覽器頁(yè)面渲染也被阻塞。

因此該方式只適用于極小時(shí)間的延時(shí),或者在web worker中使用。

那有沒(méi)有方法即使用異步的方式延時(shí),又能突破setTimeout4ms時(shí)間限制呢?

使用MessageChannel實(shí)現(xiàn)延時(shí)函數(shù)

后來(lái)想到是不是能利用MessageChannel的消息傳輸來(lái)實(shí)現(xiàn)延時(shí)作用。 然后就使用此API實(shí)現(xiàn)了一版延時(shí)函數(shù)

// 延時(shí)
function sleep(time = 1) {
    const channel = new MessageChannel();

    function timeout(callback) {
        channel.port1.onmessage = callback;
        channel.port2.postMessage(null);
    }

    return new Promise((resolve) => {
        const start = performance.now();
        const cb = () => {
            const end = performance.now();
            const delay = end - start;
            if (delay >= time) {
                resolve();
            } else {
                timeout(cb);
            }
        };

        timeout(cb);
    });
}

// 使用示例
async function run() { 
    // do something 
    // 延時(shí)1ms 
    await sleep(1); 
    console.log("sleep end!"); 
    // do something 
} 

run();

延時(shí)精度測(cè)試

// 延時(shí)時(shí)間設(shè)置為`1ms`,循環(huán)執(zhí)行`1000`次,理論執(zhí)行時(shí)間為`1000ms`
async function run() {
    console.time("run");
    for (let i = 0; i < 1000; i++) {
        await sleep(1);
    }
    console.timeEnd("run");
}

run();

// 以下為在瀏覽器console中的5次運(yùn)行結(jié)果(運(yùn)行結(jié)果在不同電腦配置下可能有出入)
// run: 1045.72607421875 ms
// run: 1049.069091796875 ms
// run: 1064.760986328125 ms
// run: 1070.867919921875 ms
// run: 1079.14892578125 ms

// 延時(shí)時(shí)間設(shè)置為`0.1ms`,循環(huán)執(zhí)行`1000`次,理論執(zhí)行時(shí)間為`100ms`
async function run2() {
    console.time("run");
    for (let i = 0; i < 1000; i++) {
        await sleep(.1);
    }
    console.timeEnd("run");
}

// 以下為在瀏覽器console中的5次運(yùn)行結(jié)果(運(yùn)行結(jié)果在不同電腦配置下可能有出入)
// run: 207.505126953125 ms
// run: 193.7880859375 ms
// run: 199.333984375 ms
// run: 207.157958984375 ms
// run: 196.8740234375 ms

可以看出使用此方式也能得到很好的效果,而且使用了異步方式來(lái)實(shí)現(xiàn),缺點(diǎn)可能就增加了cpu工作,會(huì)一定程度上影響性能。

從以上三種實(shí)現(xiàn)方式來(lái)看,在延時(shí)時(shí)間短到1ms以下時(shí),即使有方法實(shí)現(xiàn),精確度也會(huì)大大降低。并且在實(shí)現(xiàn)短時(shí)間延時(shí)函數(shù)時(shí)使用到了performance.now函數(shù),此函數(shù)的精確度也無(wú)法保證,可能進(jìn)一步加劇了延時(shí)不準(zhǔn)確的問(wèn)題。

實(shí)際上在瀏覽器中這么短時(shí)間的延時(shí)需求并不常見(jiàn),相似的需求在服務(wù)端實(shí)現(xiàn)或許能有更好的表現(xiàn)。

這里只是針對(duì)在瀏覽器環(huán)境中實(shí)現(xiàn)短時(shí)間延時(shí)的方法做了一定的探討和研究,供大家參考(nodejs不在本次討論范圍)。

到此這篇關(guān)于詳解JavaScript如何實(shí)現(xiàn)更短時(shí)間的延時(shí)函數(shù)的文章就介紹到這了,更多相關(guān)JavaScript延時(shí)函數(shù)內(nèi)容請(qǐng)搜索腳本之家以前的文章或繼續(xù)瀏覽下面的相關(guān)文章希望大家以后多多支持腳本之家!

相關(guān)文章

  • 值得分享的Bootstrap Table使用教程

    值得分享的Bootstrap Table使用教程

    一套值得分享和大家收藏的Bootstrap學(xué)習(xí)教程,完整的知識(shí)體系,系統(tǒng)的學(xué)習(xí)資料,幫助大家開(kāi)啟Bootstrap Table學(xué)習(xí)之旅,享受學(xué)習(xí)的樂(lè)趣
    2016-11-11
  • js實(shí)現(xiàn)一個(gè)簡(jiǎn)易的計(jì)算器

    js實(shí)現(xiàn)一個(gè)簡(jiǎn)易的計(jì)算器

    這篇文章主要為大家詳細(xì)介紹了js實(shí)現(xiàn)一個(gè)簡(jiǎn)易的計(jì)算器,文中示例代碼介紹的非常詳細(xì),具有一定的參考價(jià)值,感興趣的小伙伴們可以參考一下
    2021-04-04
  • 微信小程序?qū)崿F(xiàn)圖片滾動(dòng)效果示例

    微信小程序?qū)崿F(xiàn)圖片滾動(dòng)效果示例

    這篇文章主要介紹了微信小程序?qū)崿F(xiàn)圖片滾動(dòng)效果,結(jié)合實(shí)例形式分析了微信小程序基于swiper組件的圖片滾動(dòng)效果相關(guān)實(shí)現(xiàn)技巧與操作注意事項(xiàng),需要的朋友可以參考下
    2018-12-12
  • jquery下onpropertychange事件的綁定方法

    jquery下onpropertychange事件的綁定方法

    用了onchange事件,但是在輸入的時(shí)候,用Javascript計(jì)算出并填值的那一列并不會(huì)響應(yīng)onchange 事件。
    2010-08-08
  • JavaScript根據(jù)json生成html表格的示例代碼

    JavaScript根據(jù)json生成html表格的示例代碼

    這篇文章主要介紹了JavaScript根據(jù)json生成html表格的示例代碼,小編覺(jué)得挺不錯(cuò)的,現(xiàn)在分享給大家,也給大家做個(gè)參考。一起跟隨小編過(guò)來(lái)看看吧
    2018-10-10
  • javascript中Class(類)的介紹和使用方法

    javascript中Class(類)的介紹和使用方法

    在JavaScript中類(Class)是一種創(chuàng)建對(duì)象的模板,它可以用來(lái)定義對(duì)象的屬性和方法,這篇文章主要給大家介紹了關(guān)于javascript中Class(類)的介紹和使用方法的相關(guān)資料,需要的朋友可以參考下
    2024-05-05
  • 用cookies實(shí)現(xiàn)的可記憶的樣式切換效果代碼下載

    用cookies實(shí)現(xiàn)的可記憶的樣式切換效果代碼下載

    比較不錯(cuò)的用cookies實(shí)現(xiàn)的可記憶的樣式切換效果,這個(gè)思路也在一定程序,方便客戶的長(zhǎng)期使用。
    2007-12-12
  • ionic 上拉菜單(ActionSheet)實(shí)例代碼

    ionic 上拉菜單(ActionSheet)實(shí)例代碼

    ionic js 上拉菜單(ActionSheet)通過(guò)往上彈出的框,來(lái)讓用戶選擇選項(xiàng);點(diǎn)擊取消按鈕或者點(diǎn)擊空白的地方來(lái)讓它消失。本文給大家分享實(shí)現(xiàn)代碼,感興趣的朋友一起看看吧
    2016-06-06
  • javascript實(shí)現(xiàn)延時(shí)顯示提示框特效代碼

    javascript實(shí)現(xiàn)延時(shí)顯示提示框特效代碼

    本文給大家分享的是javascript通過(guò)setTimeout實(shí)現(xiàn)延時(shí)顯示提示框的特效代碼,效果非常棒,這里推薦給大家
    2016-04-04
  • JS實(shí)現(xiàn)十字坐標(biāo)跟隨鼠標(biāo)效果

    JS實(shí)現(xiàn)十字坐標(biāo)跟隨鼠標(biāo)效果

    這篇文章給大家分享一下通過(guò)JS實(shí)現(xiàn)十字坐標(biāo)跟隨鼠標(biāo)效果的代碼,有需要的朋友參考學(xué)習(xí)下吧。
    2017-12-12

最新評(píng)論