Что такое необоснованное отклонение обещания?


203

Для изучения Angular 2 я пробую их учебник.

Я получаю ошибку, как это:

(node:4796) UnhandledPromiseRejectionWarning: Unhandled promise rejection (r                                                                                                     ejection id: 1): Error: spawn cmd ENOENT
[1] (node:4796) 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.

Я прошел через различные вопросы и ответы в SO, но не смог выяснить, что такое «необработанный отказ от обещания».

Может кто-нибудь просто объяснить мне, что это такое, а также что Error: spawn cmd ENOENT, когда оно возникает и что я должен проверить, чтобы избавиться от этого предупреждения?


2
Я пропустил этот вопрос! Мне очень жаль, что это предупреждение сбивает с толку - мы действительно улучшили его в более новом Node.js, и мы скоро все исправим!
Бенджамин Грюнбаум


@BenjaminGruenbaum, это уже исправлено? Я получил ту же ошибку на узле v12.16.1
Baby Desta

1
@Babydesta хорошо, теперь мы показываем лучшую ошибку с трассировкой стека, но мы все еще не разрушаем узел при необработанных отклонениях. Возможно, нам просто нужно открыть пиар, чтобы сделать это.
Бенджамин Грюнбаум

Ответы:


200

Источником этой ошибки является тот факт, что каждое обещание должно обрабатывать отклонение обещания, т.е. иметь .catch (...) . вы можете избежать этого, добавив .catch (...) к обещанию в коде, как указано ниже.

например, функция PTest () будет разрешать или отклонять обещание на основе значения глобальной переменной somevar

var somevar = false;
var PTest = function () {
    return new Promise(function (resolve, reject) {
        if (somevar === true)
            resolve();
        else
            reject();
    });
}
var myfunc = PTest();
myfunc.then(function () {
     console.log("Promise Resolved");
}).catch(function () {
     console.log("Promise Rejected");
});

В некоторых случаях сообщение «необработанное отклонение обещания» приходит, даже если у нас написано .catch (..) для обещаний. Это все о том, как вы пишете свой код. Следующий код будет генерировать «необработанное отклонение обещания», даже если мы обрабатываем catch.

var somevar = false;
var PTest = function () {
    return new Promise(function (resolve, reject) {
        if (somevar === true)
            resolve();
        else
            reject();
    });
}
var myfunc = PTest();
myfunc.then(function () {
     console.log("Promise Resolved");
});
// See the Difference here
myfunc.catch(function () {
     console.log("Promise Rejected");
});

Разница в том, что вы обращаетесь не .catch(...)как цепь, а как отдельный элемент. По какой-то причине движок JavaScript воспринимает это как обещание без необоснованного отклонения обещания.


4
Кажется, работает, если вы добавите myFunc = myFunct.then...во втором примере.
Эйнштейн

@einstein это будет работать, потому что вы воссоздаете ту же цепочку, что и в первом примере:var x = foo(); x = x.then(...); x = x.catch(...)
randomsock

4
@einstein В вашем цепном примере, когда вы говорите: «По какой-то причине движок Java Script рассматривает его как обещание без отклонения необработанного обещания», разве это не потому, что и исключение может быть вызвано тем, с .then(() => {...})чем вы не работаете ? Я не думаю, что это делает то же самое, что когда вы их цепляете. Это?
Саймон Легг

8
@DKG Что касается вашего второго пункта, catchэто синтаксис сахара для then(undefined, onRejected). Так как вы уже вызвали myfunc и это вызвало ошибку, он не будет вызывать то же самое (undefined, onRejected) с тем же обещанием снова.
Кевин Ли

1
Где поменять? Я использую ionic 3, когда я нажимаю на команду andorid build ionic cordova, выдающую мне эту ошибку.
Сагар Кодте

34

Это когда a Promiseзавершается .reject()или в asyncисполняемый код выдается исключение, и никто .catch()не обрабатывает отклонение.

Отклоненное обещание похоже на исключение, которое всплывает к точке входа приложения и заставляет обработчик ошибок корня выдавать этот вывод.

Смотрите также


Где поменять? Я использую ionic 3, когда я нажимаю на команду andorid build ionic cordova, выдающую мне эту ошибку.
Сагар Кодте

Трудно сказать с этой информацией. Я бы посоветовал вам попытаться создать минимальное воспроизведение и создать новый вопрос для вашей конкретной ситуации.
Гюнтер Цохбауэр

я открыл награду за это. Пожалуйста, посмотрите на это stackoverflow.com/q/48145380/5383669
Сагар Кодте

22

Обещания могут быть «обработаны» после того, как они отклонены. То есть перед вызовом обработчика можно вызвать обратный вызов отклонения обещания. Это поведение немного надоедает мне, потому что можно написать ...

var promise = new Promise(function(resolve) {
kjjdjf(); // this function does not exist });

... и в этом случае Обещание молча отклоняется. Если кто-то забудет добавить обработчик перехвата, код продолжит работать без ошибок. Это может привести к затяжным и труднодоступным ошибкам.

В случае Node.js идет речь об обработке этих необработанных отклонений Promise и сообщении о проблемах. Это подводит меня к ES7 async / await. Рассмотрим этот пример:

async function getReadyForBed() {
  let teethPromise = brushTeeth();
  let tempPromise = getRoomTemperature();

  // Change clothes based on room temperature
  let temp = await tempPromise;
  // Assume `changeClothes` also returns a Promise
  if(temp > 20) {
    await changeClothes("warm");
  } else {
    await changeClothes("cold");
  }

  await teethPromise;
}

В приведенном выше примере, предположим, что toothPromise было отклонено (Ошибка: из зубной пасты!) До выполнения getRoomTempera. В этом случае произойдет необоснованное отклонение Обещания, пока не будут ожидать зубы обещания.

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

Мысли об этом?

Это связано с обсуждением в проекте Node.js здесь:

Поведение при обнаружении необработанного отказа по умолчанию

если вы напишите код так:

function getReadyForBed() {
  let teethPromise = brushTeeth();
  let tempPromise = getRoomTemperature();

  // Change clothes based on room temperature
  return Promise.resolve(tempPromise)
    .then(temp => {
      // Assume `changeClothes` also returns a Promise
      if (temp > 20) {
        return Promise.resolve(changeClothes("warm"));
      } else {
        return Promise.resolve(changeClothes("cold"));
      }
    })
    .then(teethPromise)
    .then(Promise.resolve()); // since the async function returns nothing, ensure it's a resolved promise for `undefined`, unless it's previously rejected
}

Когда вызывается getReadyForBed, он синхронно создает окончательное (не возвращаемое) обещание, которое будет иметь такую ​​же ошибку «необработанного отклонения», как и любое другое обещание (конечно, в зависимости от движка может быть ничем). (Я нахожу очень странным, что ваша функция ничего не возвращает, а это означает, что ваша асинхронная функция дает обещание для undefined.

Если я сделаю Обещание прямо сейчас без уловки и добавлю его позже, большинство реализаций «необработанная ошибка отклонения» фактически отзовет предупреждение, когда я сделаю это позже. Другими словами, async / await никоим образом не изменяет обсуждение «необработанного отказа».

чтобы избежать этой ошибки, пожалуйста, напишите код следующим образом:

async function getReadyForBed() {
  let teethPromise = brushTeeth();
  let tempPromise = getRoomTemperature();

  // Change clothes based on room temperature
  var clothesPromise = tempPromise.then(function(temp) {
    // Assume `changeClothes` also returns a Promise
    if(temp > 20) {
      return changeClothes("warm");
    } else {
      return changeClothes("cold");
    }
  });
  /* Note that clothesPromise resolves to the result of `changeClothes`
     due to Promise "chaining" magic. */

  // Combine promises and await them both
  await Promise.all(teethPromise, clothesPromise);
}

Обратите внимание, что это должно предотвратить любое необоснованное отклонение обещания.


13

« Предупреждение об устаревании : отклонение необработанного обещания устарело»

TLDR: Обещание имеет, resolveа rejectвыполнение rejectбез улова, чтобы справиться с ним, устарело, так что вам придется, по крайней мере, иметь catchна верхнем уровне.


2

В моем случае было Promise без отклонения и разрешения, потому что моя функция Promise вызвала исключение. Эта ошибка вызывает сообщение UnhandledPromiseRejectionWarning.


1

Когда я создаю экземпляр обещания, я собираюсь сгенерировать асинхронную функцию. Если функция идет хорошо, я вызываю RESOLVE, тогда поток продолжается в обработчике RESOLVE, в THEN. Если функция завершается ошибкой, завершите функцию, вызвав REJECT, и поток продолжится в CATCH.

В NodeJs устарел обработчик отклонения. Ваша ошибка - всего лишь предупреждение, и я прочитал ее в github node.js. Я нашел это.

DEP0018: необработанное отклонение обещания

Тип: Время выполнения

Необработанные обещания отклоняются. В будущем отклонения обещаний, которые не обрабатываются, завершат процесс Node.js с ненулевым кодом завершения.

Используя наш сайт, вы подтверждаете, что прочитали и поняли нашу Политику в отношении файлов cookie и Политику конфиденциальности.
Licensed under cc by-sa 3.0 with attribution required.