Що таке неспроможна відмова від обіцянки?


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.

Я переглянув різні запитання та відповіді в ТА, але не зміг з’ясувати, що таке «Неспроможна відмова у обіцянках».

Чи може хтось просто пояснити мені, що це таке, а також що Error: spawn cmd ENOENTтаке, коли воно виникає, і що я повинен перевірити, щоб позбутися цього попередження?


2
Я пропустив це питання! Мені дуже шкода, що це попередження бентежить - ми дійсно вдосконалили його в новіших Node.js, і незабаром ми зробимо все це набагато краще!
Бенджамін Грюнбаум


@BenjaminGruenbaum, це вже виправлено? Я отримав таку ж помилку на вузлі v12.16.1
Baby desta

1
@Babydesta добре, ми показуємо кращу помилку зараз із слідом стека, але ми все одно не збиваємо вузол при необроблених відхиленнях. Для цього нам, мабуть, просто потрібно відкрити PR.
Бенджамін Грюнбаум

Відповіді:


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, і це викликало помилку, він не збирається зателефонувати потім (невизначено, onRejected) на ту ж обіцянку знову.
Кевін Лі

1
Де змінити? Я використовую ionic 3, коли я потрапляю на іонну кордову збірку andorid команда, що дає мені цю помилку.
Сагар Кодте

34

Це коли a Promiseзавершено з .reject()або виняток був кинутий у asyncвиконаний код і ніхто .catch()не обробляв відхилення.

Відхилена обіцянка - це як виняток, який піднімається до точки входу в додаток і призводить до того, що обробник кореневих помилок видає цей вихід.

Дивитися також


Де змінити? Я використовую ionic 3, коли я потрапляю на іонну кордову збірку andorid команда, що дає мені цю помилку.
Сагар Кодте

Важко сказати з цією інформацією. Я б запропонував спробувати створити мінімальне відтворення та створити нове запитання для вашої конкретної ситуації.
Гюнтер Зехбауер

я відкрив щедроту за це. Будь ласка , подивіться на це stackoverflow.com/q/48145380/5383669
Сагар Kodte

22

Обіцянки можна "впоратися" після їх відхилення. Тобто, ви можете зателефонувати до відхилення виклику обіцянки перед наданням обробника вилову. Така поведінка мене трохи турбує, тому що можна писати ...

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

... і в цьому випадку Обіця відкидається мовчки. Якщо ви забудете додати обробник лову, код продовжує мовчки працювати без помилок. Це може призвести до затримок і важко знайти помилок.

У випадку з Node.js йдеться про обробку цих нерегламентованих відхилень Обіцяння та повідомлення про проблеми. Це приводить мене до асинхронізації / очікування ES7. Розглянемо цей приклад:

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;
}

У наведеному вище прикладі, припустимо, що зубиPromise були відхилені (Помилка: з зубної пасти!), Перш ніж виконати getRoomTemperature. У цьому випадку буде безрезультатне відхилення обіцянки, поки очікують зубипроміни.

Моя думка в цьому: якщо ми вважатимемо невідправлене відхилення обіцянки проблемою, обіцянки, які згодом розглядаються в очікуванні, можуть ненароком повідомити про помилки. Знову ж таки, якщо ми вважатимемо, що відмови в обігу не врегульовані, не є проблематичними, про законні помилки може не надходити повідомлення.

Думки про це?

Це пов’язано з дискусією, знайденою тут у проекті 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, він синхронно створить остаточну (не повернуту) обіцянку - яка матиме таку саму помилку "необробленого відхилення", як і будь-яка інша обіцянка (звичайно, нічого не може бути, залежно від двигуна). (Я вважаю, що дуже дивно, що ваша функція нічого не повертає, а це означає, що ваша функція асинхронізації дає обіцянку для невизначених.

Якщо я зараз зробіть обіцянку без улову, і додаю її пізніше, більшість реалізацій "помилок непоправленого відхилення" насправді буде відкликати попередження, коли я згодом оброблю його. Іншими словами, асинхронізація / очікування не змінює дискусію про "неспроможне відхилення" жодним чином, який я бачу.

щоб уникнути цієї нерівності, напишіть код таким чином:

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

«DeprecationWarning: Неопрацьований обіцяють відхилення засуджуються»

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


2

У моєму випадку «Обіцянка» не відкидала жодної рішучості, тому що моя функція «Обіцянка» кинула виняток. Ця помилка викликає повідомлення UnhandledPromiseRejectionWarning.


1

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

У NodeJs застарілий обробник відхилення. Ваша помилка - лише попередження, і я читаю її всередині node.js github. Я це знайшов.

DEP0018: необроблені відмови від обіцянок

Тип: Час виконання

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

Використовуючи наш веб-сайт, ви визнаєте, що прочитали та зрозуміли наші Політику щодо файлів cookie та Політику конфіденційності.
Licensed under cc by-sa 3.0 with attribution required.