如何在Javascript中制作一个精确的睡眠函数,可能使用承诺?

问题描述 投票:0回答:1

我试图用Javascript制作一个睡眠函数。

这个函数 drawLinesToHtmlCanvas() 的目的是为了在HTML画布上绘制随机的线条,而用户则是为了能够看到实时绘制的线条。

在这个例子中,我使用了500毫秒的延迟,但我希望能够达到1毫秒(甚至在将来低于1毫秒的分辨率)。

本来我是按照这个帖子的答案来的。sleep()的JavaScript版本是什么?

    function sleep(ms) {
      return new Promise(resolve => setTimeout(resolve, ms));
    }

    async function drawLinesToHtmlCanvas() {

        // Get canvas and context here...

        var drawSpeed = 500; // ms.

        for (i=0; i<lines; i++) {

            // Draw lines to canvas...

            await sleep(drawSpeed);
        }
    }

而且效果非常好(上图)。它的效率很高,一点也不拖累浏览器,而且让我对时间有一定的控制。

问题是 setTimeout() 似乎不能精确到1ms,而这是我对这个函数的要求。

所以我反而尝试了自己的方法,如下。

    function sleep(ms) {
        ms = parseInt(ms);
        var now = new Date();
        nowMs = now.valueOf();

        var endMs = nowMs + ms;

        while (endMs > nowMs) {
            nowMs = new Date().valueOf();
        }

        return true;
    }

    function drawLinesToHtmlCanvas() {

        // Get canvas and context here...

        var drawSpeed = 500; // ms.

        for (i=0; i<lines; i++) {

            // Draw lines to canvas...

            while (!sleep(drawSpeed));
        }
    }

这个方法非常慢,等待正确时间的while循环耗尽了所有浏览器的资源,完全无法使用。另外由于这个函数 drawLinesToHtmlCanvas() 运行时,线条没有被更新到画布元素。

的承诺解决方案。setTimeout() 是很棒的,只是对我的要求不够精确。

我可以做一个类似第一个例子的承诺吗?但是不使用 setTimeout() 它使用的算法与我的 Date() 现在与终点毫秒的对比,因为这样会更准确?

线条暂时需要能够画到1毫秒,并且有实时更新,用户需要能够看到线条被画到画布上。

javascript asynchronous promise sleep nonblocking
1个回答
1
投票

即使 setTimeout 在这种极小的时间框架上工作,这可能不会成功。当你使用回调或承诺时,你依赖于JS运行时的事件循环。这个事件循环只会以最快的速度执行你的回调。架构会施加滞后,当你低于1ms时,滞后会变得明显。回调在 setTimeout 在N毫秒过后,并不完全执行。N ms过后,它才有资格被执行。而它只有在轮到它的另一个事件循环tick时才会最终被调用。

至于你的第二种方法,它不完全是 "占用资源"。问题是你不再使用事件循环。但是你必须记住JS是单线程的。正因为如此,当JS代码不停地执行时,它根本不会让用户与UI交互。用户只能做一些事情 之间 事件回调执行。所以千万不要在浏览器中使用JS中的长运行whiles,除非你想破坏用户体验。也许除非你使用Web worker,因为它们会让你创建新的线程,但那样你就无法从那里画出任何东西。

总的来说,你把动画看成是 "画点东西然后睡觉 "的做法是相当幼稚的。虽然在浏览器中编写动画以有效地利用视频卡可能会很棘手,但执行和流畅的动画是视频卡的目的。如果你想在浏览器中制作动画,那么你必须找到专门为Canvas或WebGL上的动画制作的浏览器函数调用。https:/developer.mozilla.orgen-USdocsWebAPICanvas_APITutorialBasic_animations。

同时考虑一下,如果你真的需要如此可能的帧每秒。超过1000fps?显示器能做到吗?性能影响如何?

© www.soinside.com 2019 - 2024. All rights reserved.