为什么 Promise 对象会阻塞渲染?
Why does the Promise object block rendering?
我正在测试 Promise 对象并编写了一些代码来模拟同步的长 运行ning 任务。我正在比较 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 会以类似的方式运行,将代码添加到任务队列然后继续执行。结果的顺序是相同的,但是 运行ning 长任务的承诺似乎会阻止渲染,直到 运行ning 长任务完成。有人可以解释一下吗?
示例 运行 在 Chrome 中最好。
更新:
我并不想将 运行ning 任务并行执行到 运行,我只是想了解为什么 Promise 和 setTimeout 在我的示例中表现不同。但是,如果您确实想 运行 并行执行任务,那么 Web Workers / Worker threads 就是 Quentin 建议的方法。
但我的问题的答案似乎是 Promise 构造函数是同步的,正如 Bergi 在评论中所写的那样。
这是一个更长的 explanation
while (Date.now() - nu < 1000) {}
不会 模拟 同步的长 运行 任务。它是一个同步的长运行任务。
Promises 是一种管理 异步代码的方法,而不是使代码异步的方法,也不是模拟多线程的方法。
为此,您需要查看 workers。
- Web Workers 对于浏览器。
- Worker Threads 对于 Node.js。
我正在测试 Promise 对象并编写了一些代码来模拟同步的长 运行ning 任务。我正在比较 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 会以类似的方式运行,将代码添加到任务队列然后继续执行。结果的顺序是相同的,但是 运行ning 长任务的承诺似乎会阻止渲染,直到 运行ning 长任务完成。有人可以解释一下吗?
示例 运行 在 Chrome 中最好。
更新: 我并不想将 运行ning 任务并行执行到 运行,我只是想了解为什么 Promise 和 setTimeout 在我的示例中表现不同。但是,如果您确实想 运行 并行执行任务,那么 Web Workers / Worker threads 就是 Quentin 建议的方法。
但我的问题的答案似乎是 Promise 构造函数是同步的,正如 Bergi 在评论中所写的那样。 这是一个更长的 explanation
while (Date.now() - nu < 1000) {}
不会 模拟 同步的长 运行 任务。它是一个同步的长运行任务。
Promises 是一种管理 异步代码的方法,而不是使代码异步的方法,也不是模拟多线程的方法。
为此,您需要查看 workers。
- Web Workers 对于浏览器。
- Worker Threads 对于 Node.js。