当不能将承诺包装在承诺中时,如何使用承诺来捕获错误? [英] How can I use promises to catch errors when they might not be wrapped in a promise?

查看:63
本文介绍了当不能将承诺包装在承诺中时,如何使用承诺来捕获错误?的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

背景



我正在使用Promises,并且我有许多功能可能会或可能不会返回Promise,并且可能会或可能不会失败,例如下面的示例:

  //不返回Promise,仅返回字符串
let goodFun = function(){
return我喜欢香蕉!;
};

//炸毁!
let badFun = function(){
抛出一般错误等等!;
};

//你明白了...

因为这些功能可能或可能不会返回Promises,并且可能会或可能不会失败,我需要等待它们全部执行。为此,我有一个函数可以全部调用它们并等待它们执行:

  let asyncFun = function(){
return Promise.all([badFun(),goodFun()]);
};



问题



到目前为止很好。我的代码调用 asyncFun ,我希望它的某些功能实际上会失败。为了准备,我添加了一个注意事项:

  let executor = function(){

let numbsArray = [1、2、3];
let respArray = [];

for(让numbsArray的数量){
respArray.push(
asyncFun()
.catch(error => console.log(ʻ我失败了, $ {error}和$ {num}`))
);
}

返回Promise.all(respArray);
};

问题是渔获量没有被捕获



即使向调用 executor 的函数添加了catch也没有捕获任何东西!

  executor()
.catch(error => console.log(失败了,无法捕获错误! ));



研究



我不是真的了解为什么我的catch子句没有捕获异常。为了找出答案,我阅读了以下讨论:





这使我相信,我的所有函数 goodFun badFun ,无论如何,都必须始终返回承诺。



这对我来说很混乱,因为根据 MDN文档数组可能包含一个Promise或一个结果(例如字符串或数字)。



我还想避免在功能中添加甚至更多 个样板代码...。



问题:




  1. 如何修复我的代码,使捕获的代码添加最小或样板代码?



代码



  let goodFun = function(){返回我喜欢香蕉!;}; let badFun = function(){抛出一个一般错误等等!;};让asyncFun = function(){return Promise.all([badFun(),goodFun()]);};让执行者= function(){let numbsArray = [1,2,3];让respArray = []; for(让numbsArray的数量){respArray.push(asyncFun().catch(错误=> console.log(ʻ我因$ {error}和$ {num}`失败)))); } return Promise.all(respArray);}; executor().catch(error => console.log(惨不忍睹错误!));  

解决方案

.catch es不起作用是因为错误是同步地引发的。代码执行甚至不会执行该.catch()指令来设置捕获处理程序,因为已经抛出了错误并且代码执行已移至其他地方。如果您将所有内容包装在普通的 try-catch 中,我想您会发现它捕获了您抛出的错误。



示例:



  let goodFun = function (){返回我喜欢香蕉!;}; //炸毁!让badFun = function(){抛出一个普遍的错误等等!;} ;;尝试{Promise.all([goodFun(),badFun() ]).then(结果=> console.log(结果)).catch(错误=> console.error(错误))} catch(e){console.error(糟糕,我发现了一个错误。 不应该发生。,e);}  


这让我感到困惑,因为根据MDN文档,该数组可能包含一个Promise或一个结果(如字符串或数字)。


MDN文档n绝对正确,但是如果 badFun()引发错误,则 Promise.all 对此无能为力。 ,因为程序流将沿着调用堆栈飞去,以寻找能够捕获所引发错误的东西。



如果您不确定某些代码是否同步或基于诺言(或如果它会引发同步错误),则可以使用它来安全地封装诺言:

  function executeSafe(action){
return Promise.resolve()。then(action);
}

这将使action()免受发生的任何轰炸。 / p>

示例:



 让executeSafe =操作=> Promise.resolve()。then(action);让goodFun =()=> 我喜欢香蕉! //炸毁!让badFun =()=> {抛出一般错误等等! }; Promise.all([goodFun,badFun] .map(executeSafe)).then(results => console.log(results)).catch(error => console.error(error)) 



仅供参考,如果您使用的是Bluebird,则它具有内置方法 Promise.try ,其作用与上述 executeSafe 相同: Promise.all([goodFun ,badFun] .map(Promise.try)



这是您的完整示例,其中包含所需的修改:



  let executeSafe = action => Promise.resolve()。then(action);让goodFun =()=> 我喜欢香蕉! //炸毁!让badFun =()=> {抛出一般错误等等! };让asyncFun =()=> Promise.all([goodFun,badFun] .map(executeSafe));让执行者= function(){let numbsArray = [1,2,3];返回Promise.all(numbsArray.map(num => asyncFun().catch(error => console.log(ʻ$$ error和$ {num}`)我失败了)))));)executor() ;  



这就是 .catch 执行程序之外:



  let executeSafe = action => Promise.resolve()。then(action);让goodFun =()=> 我喜欢香蕉! //炸毁!让badFun =()=> {抛出一般错误等等! };让asyncFun =()=> Promise.all([goodFun,badFun] .map(executeSafe));让执行者= function(){let numbsArray = [1,2,3]; return Promise.all(numbsArray.map(asyncFun));} executor()。catch(error => console.error(严重捕获任何东西都失败。,错误));   


Background

I am using Promises, and I have a multitude of functions that may or may not return a Promise and that may or may not fail, like in the example below:

//does not return a Promise, simply a string
let goodFun = function(){
    return "I like bananas!";
};

//blows up!
let badFun = function(){
    throw "A general error blaahh!"; 
};

//You get the point ...

Since these functions may or may not return Promises and may or may not fail, I need to wait for all of them to execute. To achieve this I have a function to call them all and wait for their execution:

let asyncFun = function(){
    return Promise.all([badFun(), goodFun()]);
};

Problem

So far so good. My code calls asyncFun and I expect some of its functions to actually fail. To be prepared, I added a catch:

let executor = function(){

    let numbsArray = [1, 2, 3];
    let respArray = [];

    for(let num of numbsArray){
        respArray.push(
            asyncFun()
                .catch( error => console.log(`I failed with ${error} and ${num}`))
        );
    }

    return Promise.all(respArray);
};

The problem is that catch is not catching anything at all!

Even adding a catch to the function calling the executor is not catching anything !

executor()
    .catch(error => console.log("Failed miserably to catch error!"));

Research

I don't really understand why my catch clauses are not catching the exception. To find out, I read this discussion:

Which leads me to believe that all my functions goodFun and badFun, no matter what, must always return a promise.

This is confusing for me, because according to the MDN documentation the array may contain a Promise, or a result from one (like a string, or a number).

I would also like to avoid adding even more boiler plate code to my functions ....

Question:

  1. How do I fix my code, so the catches work adding a minimum or boilerplate code?

Code

let goodFun = function() {
  return "I like bananas!";
};

let badFun = function() {
  throw "A general error blaahh!";
};



let asyncFun = function() {
  return Promise.all([badFun(), goodFun()]);
};

let executor = function() {

  let numbsArray = [1, 2, 3];
  let respArray = [];

  for (let num of numbsArray) {
    respArray.push(
      asyncFun()
      .catch(error => console.log(`I failed with ${error} and ${num}`))
    );
  }

  return Promise.all(respArray);
};

executor()
  .catch(error => console.log("Failed miserably to catch error!"));

解决方案

The reason your .catches are not working is that the errors are being thrown synchronously. The code execution never even executes that .catch() instruction to set up a catch handler because the error has already been thrown and the code execution has gone elsewhere. If you wrapped everything in an ordinary try-catch, I think you'd see it catching the errors you're throwing.

Example:

let goodFun = function() {
  return "I like bananas!";
};

//blows up!
let badFun = function() {
  throw "A general error blaahh!";
};

try {
  Promise.all([goodFun(), badFun()])
    .then(results => console.log(results))
    .catch(error => console.error(error))
} catch (e) {
  console.error("Wups, I caught an error. This wasn't supposed to happen.", e);
}

This is confusing for me, because according to the MDN documentation the array may contain a Promise, or a result from one (like a string, or a number).

The MDN documentation is absolutely correct, but if badFun() throws an error, there's nothing that Promise.all can do about it, because the the program flow will be flying down the call stack looking for something to catch the error that was thrown.

If you're not sure whether some code is synchronous or promise-based (or if it will throw a synchronous error), you can use this to safely wrap it a promise:

function executeSafe(action) {
    return Promise.resolve().then(action);
}

This will shield action() from any "boom" that takes place.

Example:

let executeSafe = 
  action => Promise.resolve().then(action);

let goodFun = 
  () => "I like bananas!";

//blows up!
let badFun = 
  () => { throw "A general error blaahh!" };

Promise.all([goodFun, badFun].map(executeSafe))
  .then(results => console.log(results))
  .catch(error => console.error(error))

FYI, if you're using Bluebird, then it has a built-in method Promise.try, that serves the same purpose as executeSafe above: Promise.all([goodFun, badFun].map(Promise.try)).

Here's your full example with the needed modifications:

let executeSafe =
  action => Promise.resolve().then(action);

let goodFun =
  () => "I like bananas!";

//blows up!
let badFun =
  () => {
    throw "A general error blaahh!"
  };

let asyncFun =
  () => Promise.all([goodFun, badFun].map(executeSafe));

let executor = function() {
  let numbsArray = [1, 2, 3];

  return Promise.all(numbsArray.map(num =>
    asyncFun()
    .catch(error => console.log(`I failed with ${error} and ${num}`))
  ));
}

executor();

And here it is with the .catch outside of the executor:

let executeSafe =
  action => Promise.resolve().then(action);

let goodFun =
  () => "I like bananas!";

//blows up!
let badFun =
  () => {
    throw "A general error blaahh!"
  };

let asyncFun =
  () => Promise.all([goodFun, badFun].map(executeSafe));

let executor = function() {
  let numbsArray = [1, 2, 3];

  return Promise.all(numbsArray.map(asyncFun));
}

executor().catch(error => console.error("Miserably failed to catch anything.", error));

这篇关于当不能将承诺包装在承诺中时,如何使用承诺来捕获错误?的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆