У меня есть три теста, использующие встроенную функцию console.time (beforeBenchmark, тест и afterBenchmark).
Оба кода совершенно идентичны. Однако разница заключается в построении JS Promises API.
Первый содержит цикл в разрешении промиса, а второй содержит цикл в промисе.
Я не уверен, почему третий console.info («после цикла») занимает значительно больше времени, и я разработал его асинхронным. Спасибо за ваше время, чтобы прочитать это.
перед циклом
доБенчмарк: 0,836 мс
после цикла
послеБенчмарк: 40,987 мс
тест: 41,202 мс
перед циклом
доБенчмарк: 1,122 мс
после цикла
послеБенчмарк: 2,872 мс
тест: 43,705 мс
Я просмотрел переполнение стека, но не нашел ответа по этому поводу.
console.time("beforeBenchmark");
console.time("benchmark");
console.time("afterBenchmark");
console.info("before loop");
console.timeEnd("beforeBenchmark");
let i = 0;
let promise = new Promise(( resolve, reject ) =>
{
while (i < 10000000)
{
i++;
}
resolve();
}).then(() =>
{
console.timeEnd("benchmark")
});
console.info("after loop");
console.timeEnd("afterBenchmark");
before loop
beforeBenchmark: 0.836ms
after loop
afterBenchmark: 40.987ms
benchmark: 41.202ms
console.time("beforeBenchmark");
console.time("benchmark");
console.time("afterBenchmark");
console.info("before loop");
console.timeEnd("beforeBenchmark");
let i = 0;
let promise = Promise.resolve().then(() =>
{
while (i < 10000000)
{
i++;
}
console.timeEnd("benchmark")
});
console.info("after loop");
console.timeEnd("afterBenchmark");
before loop
beforeBenchmark: 1.122ms
after loop
afterBenchmark: 2.872ms
benchmark: 43.705ms
Обещание конструктор выполняется синхронно. Если у вас есть блокирующий код внутри new Promise(...
, этот код будет выполняться (и блокироваться) до того, как будет запущена следующая строка ниже созданного промиса. Вот почему ваш первый фрагмент имеет afterBenchmark: 40.987ms
.
С другой стороны, обратный вызов .then
будет запускать только после очистки текущего цикла событий (после завершения выполнения всего синхронного кода) — это похоже на setTimeout(fn, 0)
(не то же самое точно, поскольку setTimeout
будет выполняться на итерации следующий цикла событий, а не в конце текущая петля, но она очень похожа). Таким образом, afterBenchmark
во втором коде регистрируется до того, как запустится then
, до того, как запустится блокирующий цикл.
На самом деле, немедленно разрешенные промисы запускаются из того же цикла событий в микрозадаче. Таким образом, const oups = ()=>Promise.resolve('too bad').then(oups); oups()
заблокирует поток, а setTimeout — нет.
они оба блокируются ... хотя и в разное время ... но оба определенно блокируются ... попробуйте увеличить цикл в браузере ... оба вызовут сообщение «сценарий занимает слишком много времени»