最新国产好看的视频,伊人天堂AV在线,国产Aaaaaa视频,蜜臀视频在线观看一区,人妻av色图,密臀久久久精品影片,青青视频免费观看毛片,久草在线观看视,国产三级精品色情在线

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

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

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

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

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

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

    return promise;
}

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

run();

延時精度測試

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

run();

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

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

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

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

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

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

// 延時
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
    // 延時1ms
    sleep(1);
    console.log("sleep end!");
    // do something
}

run();

延時精度測試

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

run();

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

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

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

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

但是用此方式有一個極大的弊端,阻塞代碼運行及瀏覽器渲染。因為js為單線程運行,以同步方式做延時就會導致其他代碼執(zhí)行阻塞,瀏覽器頁面渲染也被阻塞。

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

那有沒有方法即使用異步的方式延時,又能突破setTimeout4ms時間限制呢?

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

后來想到是不是能利用MessageChannel的消息傳輸來實現(xiàn)延時作用。 然后就使用此API實現(xiàn)了一版延時函數(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 
    // 延時1ms 
    await sleep(1); 
    console.log("sleep end!"); 
    // do something 
} 

run();

延時精度測試

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

run();

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

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

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

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

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

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

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

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

相關文章

最新評論

蒙阴县| 长泰县| 蒙自县| 象山县| 大石桥市| 雷山县| 岳普湖县| 麻栗坡县| 青海省| 怀来县| 安义县| 旬邑县| 扬州市| 甘孜| 鹤壁市| 奈曼旗| 乐业县| 江孜县| 同心县| 象州县| 嘉定区| 文山县| 凤台县| 耿马| 手游| 英山县| 正定县| 乌拉特中旗| 荆州市| 襄樊市| 中江县| 辰溪县| 徐州市| 南陵县| 济宁市| 高要市| 兴安盟| 中牟县| 永胜县| 华阴市| 德惠市|