Что определяет, что отказ от обещания не обрабатывается в node.js (console / script)?

1

Javascript Обещания, если мне пришлось упростить, - это, по моему мнению, "способ действовать позже, запланированный с помощью метода .then() ".

После выполнения следующего в моем терминале:

BASE$> node
> var promise = Promise.reject("reason 42");

Поэтому я был удивлен, увидев этот результат:

> (node:8783) UnhandledPromiseRejectionWarning: reason 42
(node:8783) UnhandledPromiseRejectionWarning: Unhandled promise rejection. This error originated either by throwing inside of an async function without a catch block, or by rejecting a promise which was not handled with .catch(). (rejection id: 1)
(node:8783) [DEP0018] DeprecationWarning: Unhandled promise rejections are deprecated. In the future, promise rejections that are not handled will terminate the Node.js process with a non-zero exit code.

потому что я собирался написать.

> promise.catch(console.log);

То, что мотивирует этот вопрос:
Могу ли я быть уверенным, что node.js только тянет за этими предупреждениями (и угрозой "в будущем я полностью заступлю" из-за того, что код запускается поэтапно в console.js console/REPL?

Как node.js уже пришел к выводу, что отказ от обещаний должен быть необработанным?

Поэтому я тестировал следующее, чтобы работать по-другому

  1. Оценка "того же кода", объединенного в одну итерацию REPL:
    var promise = Promise.reject("reason 42"); promise.catch(console.log);
  2. Оценка "того же кода" из файла (например, tmp.js) с контентом
    var promise = Promise.reject("reason 42") 
    promise.catch(console.log);')
    
    через node tmp.js

оба дают ожидаемый результат " reason 42 ", не представляя предупреждения, как показано выше ранее.

Следовательно, как это получается? Могу ли мое предположение подтвердить, что определение необработанного обещания в консоли REPL узла является отражением конечного конца в каждой итерации цикла REPL?

  • 0
    I was therefore supprised to see this result because I was about to write Он не может читать ваши мысли - в тот момент он даже не подозревал, что с ним будут работать. Таким образом, вместо того, чтобы ждать какое-то неопределенное количество времени и затем проверять, не отклонен ли по-прежнему необработанный запрос, он немедленно выдаст запрос.
Теги:
promise

2 ответа

2
Лучший ответ

Для того, чтобы отказ от обещания считался обработанным, он должен быть прикован цепью с catch или then с двумя аргументами на одном тике.

Это вызовет UnhandledPromiseRejectionWarning:

var promise = Promise.reject("reason 42");

setTimeout(() => {
  promise.catch(console.error);
});

Это не вызовет UnhandledPromiseRejectionWarning:

var promise = Promise.reject("reason 42");
promise.catch(console.error);

Асинхронно оцениваемые строки в Node.js REPL приводят к задержке между ними. Чтобы синхронно оценивать строки в том порядке, в котором они были записаны, можно использовать режим редактора. Или код можно записать так, чтобы его однозначно оценивали как блок:

;{
var promise = Promise.reject("reason 42");
promise.catch(console.error);
}

Или IIFE:

(() => {
var promise = Promise.reject("reason 42");
promise.catch(console.error);
})()
  • 0
    поэтому отклонения асинхронных конструкций (т. е. обещаний) необходимо обрабатывать синхронно, и в рамках REPL две итерации не квалифицируются как синхронные , правильно ли я понимаю?
  • 0
    Это правильно.
Показать ещё 1 комментарий
2

Я хотел бы распространить на @estus ответ, особенно первое предложение:

Для того, чтобы отказ от обещания считался обработанным, он должен быть прикован цепью с уловкой или затем с двумя аргументами на одном тике.

Я не согласен с этим. Я бы аргумент, что каждое обещание, где then или catch еще назвать это хорошо, но при вызове этих методов вы создаете новые посылы, и они только что унаследовали эту проблему.

Мы часто говорим о цепочках обещаний, но на самом деле это дерево, так как вы можете разделить несколько "дочерних обещаний" от одного и того же "родителя", и ошибка затрагивает их все.

const root = Promise.reject("reason 42");

const a = root.then(value => value*2)
              .then(...);

const b = root.then(value => value*3)
              .then(...);

Итак, вы строите цепочку/дерево обещаний; возникает ошибка. Ошибка распространяется на дочерние обещания в этом дереве,... Если эта (или любая другая) ошибка достигает любого обещания листа (не зацепившись где-то вдоль линии), вы получите UnhandledPromiseRejectionWarning.

Есть миллион вещей, которые вы можете сделать с обещаниями и тем, как вы их связываете/разделяете и как/где вы поймаете свои ошибки,... поэтому лучшее резюме, которое я могу вам дать:

Поскольку Promises - это все время, у вас есть время, пока ошибка не достигнет конца цепи, чтобы catch ее.

Могу ли я быть уверенным, что node.js только тянет за этими предупреждениями (и угрозой "в будущем я полностью заступлю" из-за того, что код запускается поэтапно в консоли node.js

да

  • 0
    Хорошо, это, конечно, еще одна ловушка. Хотя это и важно, однако реальная путаница и основная проблема моего вопроса заключалась в том, чтобы получить подтверждение того, что a) catch() отклонения должен выполняться синхронно, чтобы избежать предупреждения, и b) каждая итерация REPL консоли node.js не является синхронно больше с предыдущим. +1, как это, однако, выделить еще одну ловушку.

Ещё вопросы

Сообщество Overcoder
Наверх
Меню