¿Qué es un rechazo de promesa no manejada?

203

Para aprender Angular 2, estoy probando su tutorial.

Recibo un error como este:

(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.

Revisé diferentes preguntas y respuestas en SO, pero no pude descubrir qué es un "rechazo de promesas no manejadas".

¿Alguien puede simplemente explicarme qué es y también qué Error: spawn cmd ENOENTes, cuándo surge y qué debo verificar para deshacerme de esta advertencia?

Mohammad Sadiqur Rahman
fuente
2
Me perdí esta pregunta! Lamento mucho esta advertencia que es confusa: ¡realmente la mejoramos en el nuevo Node.js y pronto haremos todo mejor!
Benjamin Gruenbaum
Posible duplicado de: stackoverflow.com/questions/38265963/…
Christophe Roussy
@BenjaminGruenbaum, ¿ya está solucionado? Recibí el mismo error en el nodo v12.16.1
Baby desta
1
@Babydesta, mostramos un mejor error ahora con un seguimiento de pila, pero aún no bloqueamos el nodo en rechazos no controlados. Probablemente solo necesitemos abrir un RP para hacer eso.
Benjamin Gruenbaum

Respuestas:

200

El origen de este error radica en el hecho de que se espera que todas y cada una de las promesas manejen el rechazo de la promesa, es decir, que tengan un .catch (...) . puede evitar lo mismo agregando .catch (...) a una promesa en el código como se indica a continuación.

por ejemplo, la función PTest () resolverá o rechazará una promesa basada en el valor de una variable global 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");
});

En algunos casos, el mensaje de "rechazo de promesas no manejadas" aparece incluso si tenemos .catch (..) escrito para promesas. Se trata de cómo escribes tu código. El siguiente código generará un "rechazo de promesa no manejado " aunque lo estemos manejando 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");
});

La diferencia es que no lo manejas .catch(...)como una cadena sino como algo separado. Por alguna razón, el motor de JavaScript lo trata como una promesa sin un rechazo de promesa no manejado.

Daksh
fuente
44
Parece funcionar, si agrega myFunc = myFunct.then...en el segundo ejemplo.
einstein
@einstein parecerá funcionar porque está recreando la misma cadena que en el primer ejemplo:var x = foo(); x = x.then(...); x = x.catch(...)
randomsock
44
@einstein En su ejemplo desencadenado, cuando dice "Por alguna razón, el motor de Java Script lo trata como una promesa sin un rechazo de promesa no manejado", ¿no es esto porque podría lanzarse una excepción en la .then(() => {...})que no está manejando? No creo que esto esté haciendo lo mismo que cuando los encadena. ¿Lo es?
Simon Legg
8
@DKG Con respecto a su segundo punto, catches una sintaxis de azúcar para then(undefined, onRejected). Como ya llamó a myfunc y eso provocó un error, no volverá a llamar (indefinido, rechazado) en la misma promesa nuevamente.
Kevin Lee
1
Donde cambiar Estoy usando ionic 3 cuando golpeé el comando iónico cordova build andorid dándome este error.
Sagar Kodte
34

Esto es cuando Promisese completa .reject()o se lanza una excepción en un asynccódigo ejecutado y no.catch() maneja el rechazo.

Una promesa rechazada es como una excepción que emerge hacia el punto de entrada de la aplicación y hace que el controlador de error raíz produzca esa salida.

Ver también

Günter Zöchbauer
fuente
Donde cambiar Estoy usando ionic 3 cuando golpeé el comando iónico cordova build andorid dándome este error.
Sagar Kodte
Difícil de decir con esta información. Le sugiero que intente crear una reproducción mínima y cree una nueva pregunta para su situación específica.
Günter Zöchbauer
He abierto recompensas por ello. Por favor mirarlo stackoverflow.com/q/48145380/5383669~~V~~singular~~3rd
Sagar Kodte
22

Las promesas pueden "manejarse" después de ser rechazadas. Es decir, se puede llamar la devolución de llamada de rechazo de una promesa antes de proporcionar un controlador de captura. Este comportamiento es un poco molesto para mí porque uno puede escribir ...

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

... y en este caso, la Promesa es rechazada en silencio. Si uno olvida agregar un controlador catch, el código continuará ejecutándose silenciosamente sin errores. Esto podría conducir a errores persistentes y difíciles de encontrar.

En el caso de Node.js, se habla de manejar estos rechazos de Promesa no manejados y reportar los problemas. Esto me lleva a ES7 async / wait. Considere este ejemplo:

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

En el ejemplo anterior, suponga que se rechazó el mensaje toothPromise (Error: ¡sin pasta de dientes!) Antes de que se cumpliera getRoomTemperature. En este caso, habría un rechazo no prometido de Promise hasta que aguarden los dientes.

Mi punto es este ... si consideramos que los rechazos de promesas no manejadas son un problema, las promesas que luego son manejadas por una espera podrían ser reportadas inadvertidamente como errores. Por otra parte, si consideramos que los rechazos de Promesa no manejados no son problemáticos, los errores legítimos podrían no ser reportados.

¿Pensamientos sobre esto?

Esto está relacionado con la discusión que se encuentra en el proyecto Node.js aquí:

Comportamiento predeterminado de detección de rechazo no controlado

si escribe el código de esta manera:

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
}

Cuando se invoca getReadyForBed, creará sincrónicamente la promesa final (no devuelta), que tendrá el mismo error de "rechazo no controlado" que cualquier otra promesa (por supuesto, podría no ser nada, dependiendo del motor). (Me parece muy extraño que su función no devuelva nada, lo que significa que su función asincrónica produce una promesa para indefinido.

Si hago una Promesa en este momento sin una trampa, y agrego una más tarde, la mayoría de las implementaciones de "error de rechazo no controlado" en realidad retractarán la advertencia cuando más tarde la maneje. En otras palabras, async / await no altera la discusión del "rechazo no controlado" de ninguna manera que pueda ver.

Para evitar este problema, escriba el código de esta manera:

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

Tenga en cuenta que esto debería evitar cualquier rechazo de promesa no controlado.

programador anis
fuente
13

"DeprecationWarning: los rechazos de promesas no controladas son obsoletos"

TLDR: una promesa ha quedado obsoleta resolvey reject, al hacerlo rejectsin capturarla, está en desuso, por lo que tendrá que tener al menos un catchnivel superior.

Christophe Roussy
fuente
2

En mi caso, Promise no rechazó ni resolvió, porque mi función Promise arrojó una excepción. Este error causa el mensaje UnhandledPromiseRejectionWarning.

Diniz
fuente
1

Cuando instancia una promesa, voy a generar una función asincrónica. Si la función funciona bien, entonces llamo a RESOLVE y el flujo continúa en el manejador RESOLVE, luego ENTONCES. Si la función falla, finalice la función llamando a RECHAZAR y luego el flujo continúa en la CAPTURA.

En NodeJs están en desuso el controlador de rechazo. Su error es solo una advertencia y lo leí dentro de node.js github. Encontré esto.

DEP0018: rechazos de promesas no manejadas

Tipo: tiempo de ejecución

Los rechazos de promesas no manejadas están en desuso. En el futuro, los rechazos de promesas que no se manejan terminarán el proceso de Node.js con un código de salida distinto de cero.

Κωλζαρ
fuente