为什么 Chrome 告诉我我有一个未处理的拒绝,而我明明正在处理它?

Why is Chrome telling me I have an Unhandled Rejection when I clearly am handling it?

我正在为 Javascript 承诺使用 "defer" 模式,让我 return 对调用函数的承诺,然后在稍后的某个时间,在某些情况下,解决或拒绝那个承诺。

正如您在我提供的代码中看到的那样,除了在浏览器中出现 Unhandled Rejection 错误之外,一切都按预期工作。

function promiseGenerator() {
  const deferred = {};

  const promise = new Promise((resolve, reject) => {
    deferred.resolve = resolve;
    deferred.reject = reject;
  });
  deferred.promise = promise;

  return deferred;
}

const generatedPromise = promiseGenerator();

generatedPromise.promise.then(res => {
  console.log("A string deferred resolved!", res);
});

generatedPromise.promise.then().catch(e => {
  console.log("This is the catch", e);
});

generatedPromise.reject("Oh no");

我期待在控制台中看到 This is the catch Oh no - 我做到了。但为什么我会收到错误消息?很明显,我的拒绝 正在 处理中!

注意 我不想(必然)将捕获链接到 then 因为我可能想在其他地方单独添加这个捕获代码

这是一个 Codesandbox link https://codesandbox.io/embed/deferred-promise-catch-vanilla-pjor9

为了捕获传递给 new Promise() 构造函数的回调中抛出的错误,需要将 catch 块附加到 .then() 的返回值,而不是承诺本身。

generatedPromise.promise
  .then(res => {
    console.log("A string deferred resolved!", res);
  })
  .catch(e => {
    console.log("This is the catch", e);
  });

generatedPromise.reject 对象是对您传递给构造函数 (resolve, reject) => {} 的回调中的 reject 参数的引用。

同理,generatedPromise.promise 是对 new Promise() 返回对象的引用。

那么唯一可以捕获调用 genetratedPromise.reject() 引发的错误的方法是将 .catch() 链接到 .then()。没有别的办法了。

这是看待这个问题的另一种方式:

const promise = new Promise((resolve, reject) => {
  reject('test')
});


promise.catch(err => 'foo'); // throws unhandled promise rejection. Cause you rejected, but didn't catch it after the .then statement

promise.then(() => {}).catch(err => 'foo'); // doesn't throw rejection

您在承诺链中使用了 catch。 generatedPromise.promise.then(res => { console.log("A string deferred resolved!", res); }).catch(error => console.log('error));

编辑:有人更快。

Edit2:看到其他 post 的评论。可能有办法,但不是很好的做法。

  function promiseGenerator() {
  const deferred = {};


//do your function stuff here
try{
  const promise = new Promise((resolve, reject) => {
    deferred.resolve = resolve;

 });
} catch(ex){
const promise = new Promise((resolve, reject) => {
    deferred.resolve = resolve(ex);
  });
}

  return deferred;
}

这样一个承诺有两个不同的结果,另一种方法是使用 try catch 块,而不是 if else 语句,但这完全取决于您的应用程序。

Promise 拒绝未在 .then() 回调中处理,当您首先附加 then() 回调并且承诺被拒绝时,错误被视为未处理,因为没有 catch()then().

之后

处理这个问题的正确方法是添加一个 catch() 链接到 then():

function promiseGenerator() {
  const deferred = {};

  const promise = new Promise((resolve, reject) => {
    deferred.resolve = resolve;
    deferred.reject = reject;
  });
  deferred.promise = promise;

  return deferred;
}

const generatedPromise = promiseGenerator();

//Error from the rejection is handled in the catch
generatedPromise.promise.then(res => {
  console.log("A string deferred resolved!", res);
}).catch(e => {
  console.log("This is the catch", e);
});

generatedPromise.reject("Oh no");

另一种方法是将拒绝处理程序作为 then() 回调的第二个参数传递以处理 Promise 拒绝:

function promiseGenerator() {
  const deferred = {};

  const promise = new Promise((resolve, reject) => {
    deferred.resolve = resolve;
    deferred.reject = reject;
  });
  deferred.promise = promise;

  return deferred;
}

const generatedPromise = promiseGenerator();

//Error from the rejection is handled in the second callback
generatedPromise.promise.then(res => {
  console.log("A string deferred resolved!", res);
},
err => {
  console.log("This is the catch", err);
});

generatedPromise.reject("Oh no");