Заобіцяючи, чому браузери двічі повертають відхилення, але не двічі?


10

У мене виникають проблеми з розумінням javaScript promises. Я написав наступний код:

var p = new Promise(function(resolve,reject){

    reject(Error("hello world"));
});

setTimeout(()=>p.catch(e=>console.log(e)),5000);

Я одразу бачу це на консолі розробника Chrome: введіть тут опис зображення

Але після того, як я зачекаю 5 секунд, повідомлення автоматично змінюється на чорний, як це зображення: введіть тут опис зображення

Я ніколи раніше не бачив такої поведінки між кодом javaScript і консоллю розробника, де мій код javaScript може "змінювати наявний вміст" в консолі розробника.

Тому я вирішив перевірити, чи не трапляється така сама ситуація resolve, написавши цей код:

var p = new Promise(function(resolve,reject){

    resolve("hello world");
});

setTimeout(()=>p.then(e=>console.log(e)),5000);

Але в цій ситуації моя консоль розробника нічого не показує до 5 секунд, на яку вона потім друкує hello world.

Чому resolveі rejectоброблені таким чином , по- різному з точки зору , коли вони викликаються?


ДОПОМОГА

Я також написав цей код:

var p = new Promise(function(resolve,reject){

    reject(Error("hello world"));
});

setTimeout(()=>p.catch(e=>console.log("errors",e)),5000);
setTimeout(()=>p.catch(e=>console.log("errors 2",e)),6000);
setTimeout(()=>p.catch(null),7000);

Це призводить до декількох виходів на консоль розробника. Червона помилка в часі 0, червона змінюється на чорну за 5 секунд разом із текстом errors hello world, потім нове повідомлення про помилку за час 6 секунд errors 2 hello world, потім червоне повідомлення про помилку за час 7 секунд. Зараз я дуже розгублений у тому, скільки разів rejectнасправді викликають .... я загублений ...


1
Лише вбік: var p = new Promise(function(resolve,reject){ reject(Error("hello world")); });можна більш ідіоматично і стисло записати як var p = Promise.reject(Error("hello world"));:-)
TJ Crowder

1
Дивовижне питання.
TJ Crowder

Відповіді:


11

Ого, це справді круто. Я ніколи не бачив, щоб консолі так робили. (У ньому є й інші форми динамічної поведінки, хоча так ...) Ось що відбувається:

У першому випадку завершення виконання коду всього, що знаходиться поза setTimeoutкодом зворотного дзвінка, завершується, і стек виконання повертається так, що працює лише " код платформи " (як це називає Обіцянки / A + специфікація), а не JavaScript-код (на даний момент). У цей момент обіцянку відкидають, і ніщо не справляється з відхиленням, тож це неприховане відхилення і devtools повідомляє про це як таке.

Потім , через п’ять секунд, ваш зворотний дзвінок запускається та приєднує обробник відхилення. На даний момент відхилення вже не є незмінним. Мабуть, Chrome / V8 / devtools працюють разом, щоб вилучити непогашене попередження про відхилення з консолі. Натомість ви бачите те, що ви надсилаєте в обробник відхилень через console.log. Якщо ви приєднали обробник відхилень раніше, ви не отримаєте цієї необробленої помилки відхилення.

Це не відбувається з виконанням, тому що не обробка виконання не є умовою помилки. Не обробка відхилення є.


1
О, це має сенс. Я помітив, що FireFox обробляє це дещо інакше. Але ок, зараз має більше сенсу.
Джон

1
Я написав так само у відповідь, але ТАК завантажив ваше, так що я не розмістив свою. Приємне пояснення! +1
FZs
Використовуючи наш веб-сайт, ви визнаєте, що прочитали та зрозуміли наші Політику щодо файлів cookie та Політику конфіденційності.
Licensed under cc by-sa 3.0 with attribution required.