为什么 Promise 对象会阻塞渲染? [英] Why does the Promise object block rendering?

查看:57
本文介绍了为什么 Promise 对象会阻塞渲染?的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

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

I was testing the Promise object and wrote some code that simulates a long running task that is synchronous. I was comparing Promise and setTimeout - see 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(`
setTimeout test starts after ${Date.now() - now} ms`);
            setTimeout(() => {
                slow();
                log(`
Slow function completes after ${Date.now() - now} ms`);
            }, 0);
            log(`
Event listener completes after ${Date.now() - now} ms`);
        });

        const promiseButton = document.getElementById('promise-test');
        promiseButton.addEventListener('click', () => {
            const now = Date.now();
            log(`
setTimeout test starts after ${Date.now() - now} ms`);
            getSlowPromise().then(res => log(`
Promise completes after ${Date.now() - now} ms`));
            log(`
event 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 的行为方式类似,将代码添加到任务队列中,然后继续执行.结果的顺序是相同的,但是长时间运行的任务的承诺似乎会阻止渲染,直到长时间运行的任务完成.有人能解释一下吗?

I thought Promise and setTimeout would behave in a similar way, add the code to the task queue and then continue the execution. The order of the results are the same but the promise with a long running task seems to block the rendering until the long running task completes. Can someone explain this?

该示例在 Chrome 中运行最佳.

The example runs best in Chrome.

更新:我并不是要让长时间运行的任务并行运行,我只是想了解为什么 Promise 和 setTimeout 在我的示例中表现不同.但是,如果您确实想并行运行任务,那么正如 Quentin 建议的那样,Web Workers/Worker 线程是可行的方法.

Update: I'm not trying to make the long running task to run in parallel, I just want to understand why Promise and setTimeout behave differently in my example. But if you do want to run the task in parallel then Web Workers / Worker threads is the way to go as Quentin suggests.

但是我的问题的答案似乎是 Promise 构造函数是同步的,正如 Bergi 在评论中所写的那样.这是一个更长的 说明

But the answer to my question seems to be that Promise constructors are synchronous as Bergi writes in a comment. Here is a longer explanation

推荐答案

while (Date.now() - nu <1000) {}模拟一个长时间运行的同步任务.一个长时间运行的同步任务.

while (Date.now() - nu < 1000) {} doesn't simulate a long running task that is syncronous. It is a long running task that is syncronous.

Promise 是一种管理异步代码的方式,而不是一种使代码异步的方式,也不是一种模拟多线程的方式.

Promises are a way to manage asynchronous code, not a way to make code asynchronous, nor a way to simulate multithreading.

为此,您需要查看工人.

  • Web Workers for browsers.
  • Worker Threads for Node.js.

这篇关于为什么 Promise 对象会阻塞渲染?的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆