Я тестировал объект Promise и написал код, который имитирует длительную задачу, которая является синхронной. Я сравнивал Promise и setTimeout - см. Скрипку:
<!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 будут вести себя аналогичным образом, добавьте код в очередь задач, а затем продолжите выполнение. Порядок результатов один и тот же, но обещание с долговременной задачей, похоже, блокирует рендеринг, пока не завершится длительная работа. Может кто-нибудь объяснить это?
Пример лучше всего работает в Chrome.
Обновление: я не пытаюсь запустить параллельное выполнение задачи, я просто хочу понять, почему Promise и setTimeout ведут себя по-другому в моем примере. Но если вы хотите запустить задачу параллельно, то потоки Web Workers/Worker - это путь, который предлагает Quentin.
Но ответ на мой вопрос, похоже, заключается в том, что конструкторы Promise синхронны, как пишет Bergi в комментарии. Вот более длинное объяснение
while (Date.now() - nu < 1000) {}
не моделирует длительную выполняемую задачу, которая является синхронной. Это давно работает задача, которая является Синхронной.
Обещания - это способ управления асинхронным кодом, а не способ сделать асинхронный код, а также способ имитации многопоточности.
Для этого вам нужно посмотреть на рабочих.
while (Date.now() - nu < 1000) {}
блокирует рендеринг - обещания неwhile (Date.now() - nu < 1000) {}
подобные синхронные циклыsetTimeout
также выполняются в другой части цикла событий, чем микротрубы, такие как вызовыPromise.then
. Хотя это не проблема с вашим примером кода, это вызовет у вас проблемы, если вы ожидаете, что они будут эквивалентны во всех случаях.