提问者:小点点

为什么Promise对象会阻止渲染?


我正在测试Promise对象,并编写了一些代码来模拟一个长时间运行的同步任务。我在比较Promise和setTimeout--参见Fiddle:

<!DOCTYPE html>
<html>

  <head>
    <link rel="stylesheet" href="style.css">
  </head>

  <body>
    <h2>Promise vs setTimeout</h2>
    <div><button id="settimeout-test">setTimeout with slow running function</button></div>
    <div><button id="promise-test">Promise and slow running function</button></div>
    <div><button id="clear">Clear Results</button></div>
    <h5>Results</h5>
    <div id="result"></div>

    <script>
        const slow = function() {
            let nu = Date.now();
            while (Date.now() - nu < 1000) {}
        }
        const getSlowPromise = () => new Promise(resolve => {
                slow();
                resolve();
        });
        const resultsElement = document.getElementById('result')
        const log = (message) => {
            resultsElement.innerText += message;
        }  

        const settimeoutButton = document.getElementById('settimeout-test');
        settimeoutButton.addEventListener('click', () => {
            const now = Date.now();
            log(`\nsetTimeout test starts after ${Date.now() - now} ms`);
            setTimeout(() => {
                slow();
                log(`\nSlow function completes after ${Date.now() - now} ms`);
            }, 0);
            log(`\nEvent listener completes after ${Date.now() - now} ms`);
        });

        const promiseButton = document.getElementById('promise-test');
        promiseButton.addEventListener('click', () => {
            const now = Date.now();
            log(`\nsetTimeout test starts after ${Date.now() - now} ms`);
            getSlowPromise().then(res => log(`\nPromise completes after ${Date.now() - now} ms`));
            log(`\nevent listener completes after ${Date.now() - now} ms`);
        })

        const clear = () => resultsElement.innerText = '';
        const clearButton = document.getElementById('clear');
        clearButton.addEventListener('click', () => clear());

    </script>

  </body>

</html>

我以为Promise和setTimeout会以类似的方式运行,将代码添加到任务队列中,然后继续执行。结果的顺序是相同的,但是长时间运行任务的promise似乎会阻止呈现,直到长时间运行的任务完成。有人能解释一下吗?

这个例子在Chrome中运行得最好。

更新:我并不是要使长时间运行的任务并行运行,我只是想了解为什么在我的示例中Promise和setTimeout的行为不同。但是,如果您确实希望并行运行任务,那么Web Workers/Workers threads是一种可行的方法,正如Quentin建议的那样。

但我的问题的答案似乎是,Promise构造函数是同步的,正如Bergi在一篇评论中所写的那样。下面是一个更长的解释


共1个答案

匿名用户

while(date.now()-nu<1000){}不模拟同步的长时间运行任务。这是一个长时间运行的任务,是同步的。

承诺是管理异步代码的一种方式,而不是使代码异步化的方式,也不是模拟多线程的方式。

为此,你需要看看工人。

  • 用于浏览器的Web Workers.
  • node.js的工作线程