繁体   English   中英

Promise.all带有try / catch模拟

[英]Promise.all with try/catch simulation

我目前正在尝试,并尝试使自己熟悉诺言,我将贯穿介绍性概念,并深入探讨问题。 NodeJS中 ,使用库BlueBird 我不想推迟函数调用,我也不想污染过多的代码,即使这是介绍性的编码以熟悉前提,因为当尝试更高级的概念时,我会得到迷失了他们。 我尝试在try块中使用'asyn / await',但是上帝使代码混乱,并且无法正常工作。

  • 我不想使用Promise.settle,我仍然想在函数拒绝时退出,如果出现错误,我只想留在Catch块中。
  • 我不想以某种怪异的方式使用async / await,yield或generators来停止代码流,因为这不利于预期的实践。
  • 如果预定的解决方案不对,请不要仅仅说错了,我理解人们的时间很宝贵,但是由于对语言的理解有限,因此可能会向我扔出尽可能多的文档,或者原因我错了总比没有受赞赏。
  • 我已经在CoffeeScript中看到了该概念的实现,但目前还没有一个可行的理由转向该语法系统,因为在接下来的几个月中我可能会使用的大多数语言都是裸机节点后端管理。

Promise包含一个内置的捕获机制,如果处理标准的单个Promise,该机制将完美工作。

 // Try/Catch style Promises funcTwo = function(activate) { return new Promise(function(resolve, reject) { var tmpFuncTwo; if (activate === true) { tmpFuncTwo = "I'm successful" resolve(tmpFuncTwo) } else if (activate === false) { tmpFuncTwo = "I'm a failure."; reject(tmpFuncTwo) } else { tmpFuncTwo = "Oh this is not good." throw new Error(tmpFuncTwo); } }); } funcTwo(true) .then(val => { console.log("1: ", val) return funcTwo() }) .catch(e => { console.log("2: Err ", e.message) }) 

使我有些困惑的是尝试与Promise保持相同的前提。所有错误都没有得到处理,因为抛出直接推到主Controller。 从此代码段引发的异常永远不会使其到达Catch块。

 funcThree = function(val) { return new Promise(function(resolve, reject) { if (val > 0) resolve((val + 1) * 5) else if (val < 0) reject(val * 2) else throw new Error("No work for 0"); }) } // Output in Dev Console /* Extrending to the catch block handling, This will fail, the exception is thrown, and ignores the catch block. Terminating the program. */ Promise.all([funcThree(1), funcThree(0), funcThree(-3)]) .then(function(arr) { for (var ind = 0; ind < arr.length; ind++) { console.log(arr) }; }, function(arr) { console.log(arr) }) .catch(function(e) { console.log("Error") }) 

我尝试了一种简单的解决方法,但是对于该语言我有些陌生,并且不确定这是否遵循“最佳实践”,因为它们已从Python准则中深入人心。

 // Promise all, exceptionHandling funcThree = (val) => { return new Promise(function(resolve, reject) { if (val > 0) resolve((val + 1) * 5) else if (val < 0) reject(val * 2) else { var tmp = new Error("No work for 0"); tmp.type = 'CustomError'; reject(tmp); } }) } /* This works, and doesn't cause any type of mixup */ Promise.all([funcThree(1), funcThree(0), funcThree(-3)]) .then( arr => { for (var ind = 0; ind < arr.length; ind++) { console.log(arr) }; }, rej => { if (rej.type == 'CustomError') throw rej; console.log(arr) }) .catch(e => { console.log("Catching Internal ", e.message) }) 

这正在使用Native Promise库以及bluebird

有没有一种更本地化的方法来解决这个问题,

关于jfriend00的评论。 我的意思是说,除了try-catch块之外,我不希望通过任何其他方式来处理异常。 当我尝试使用与常规诺言相同的格式时,事情会完美地对齐,并且我的捕获得到确认,并且错误得以解决。 由于Promise.all只能解析/拒绝,所以我认为没有一种干净的方法可以将第二个代码段中从第二次调用funcTwo引发的异常委派给他人。 或多或少我不确定作为变通办法所做的事情,“拒绝,检查拒绝是否传递了错误,然后将其丢弃”,这是一个很好的解决方案,或者是否会引起严重的问题随着代码的扩展。

由于Promise.all只能解析/拒绝,所以我认为没有一种干净的方法可以将第二个代码段中从第二次调用funcTwo引发的异常委派给他人。

在您的此代码块中:

// Try/Catch style Promises
funcTwo = function(activate) {
  return new Promise(function(resolve, reject) {
    var tmpFuncTwo;
    if (activate === true) {
      tmpFuncTwo = "I'm successful"
      resolve(tmpFuncTwo)
    } else if (activate === false) {
      tmpFuncTwo = "I'm a failure.";
      reject(tmpFuncTwo)
    } else {
      tmpFuncTwo = "Oh this is not good."
      throw new Error(tmpFuncTwo);
    }
  });
}

throwreject()之间没有区别。 throw被Promise构造函数捕获,并变成了reject() 就个人而言,在这种情况下,我更喜欢只使用reject() ,因为我认为函数调用比异常要快一些。

我不知道是否在规范中对此进行了编码,但是通常认为拒绝Error对象是一个好主意。 因此,我将这样编写您的代码:

function funcTwo(activate) {
  return new Promise(function(resolve, reject) {
    if (activate === true) {
      resolve("I'm successful");
    } else {
      let errMsg = activate === false ? "I'm a failure." : "Oh this is not good.";
      reject(new Error(errMsg));
    }
  });
}

答应解决或拒绝。 没有第三种错误条件与拒绝条件不同。 异常只是拒绝。 因此,如果您要返回三个状态(如上面的代码),则必须决定如何将这三个状态分别设置为resolvereject

由于这只是示例代码,因此这里没有具体建议。 如果activate === false实际上不是错误,只是另一种类型的完成,不应终止您在Promise.all()其他promise,那么您希望这种情况是resolve() ,而不是reject() 但是,没有硬性规定是什么-它实际上仅取决于您希望呼叫者自然且简单的行为,因此,从一种情况到另一种情况都不同。

此外,如果您不控制此处的funcTwo的代码,则可以在将其传递给Promise.all()之前,在其上放置.catch()处理函数,然后将特定的拒绝变为解析如果那是您希望Promise.all()逻辑起作用的方式。 Promises链,因此您可以在将其传递给更高级别的操作之前修改其输出。 它类似于在较低级别使用try / catch来捕获和异常并对其进行处理,因此较高级别的代码不必看到它(有时是适当的)。

或多或少我不确定作为变通办法所做的事情,“拒绝,检查拒绝是否传递了错误,然后将其丢弃”,这是一个很好的解决方案,或者是否会引起严重的问题随着代码的扩展。

在您的Promise.all()代码中:

/*
  This works, and doesn't cause any type of mixup
 */
Promise.all([funcThree(1), funcThree(0), funcThree(-3)]).then(arr => {
  for (var ind = 0; ind < arr.length; ind++) {
    console.log(arr[index]);
  }
}, rej => {
  if (rej.type == 'CustomError')
    throw rej;
  console.log(arr)
}).catch(e => {
  console.log("Catching Internal ", e.message)
})

您的第一个拒绝处理程序并没有真正帮助您。 它没有做您不能只在一个.catch()处理函数中做的任何事情。 让我重复一遍。 许诺rejectresolve只有两个结果。 没有例外的第三个结果。 在promise回调中发生的异常仅会成为拒绝。 因此,您的上述代码可以更改为:

/*
  This works, and doesn't cause any type of mixup
*/
Promise.all([funcThree(1), funcThree(0), funcThree(-3)]).then(arr => {
  for (var ind = 0; ind < arr.length; ind++) {
    console.log(arr)
  };
}).catch(e => {
  // there is no value for arr here, no result - only a reject reason
  console.log("Catching Internal ", e.message)
  if (rej.type === "CustomError") {
      // do something special for this type of error
  }
  // unless you rethrow here, this rejection will be considered handled
  // and any further chained `.then()` will see the promise as resolved
  // but since there is no return value, the promise will be resolved
  // with an undefined result
});

如果你想捕捉的拒绝funcThree()早期,足量,它可以让承诺的其余Promise.all()仍然被跟踪,仍然可以得到他们的结果,那么你就可以得到一个Promise.settle()实现无论有多少拒绝,您都可以遵循所有承诺的结论,或者您可以编写自己的特殊情况:

function funcFour(val) {
    return funcThree(val).catch(err => {
       // catch and examine the error here
       if (err.type === "CustomError") {
           // allow things to continue on here for this specific error
           // and substitute null for the value.  The caller will have
           // to see null as a meaningful result value and separate from
           // a non-null result
           return null;
       } else {
           // Not an error we recognize, stop further processing
           // by letting this promise reject
           throw err;
       }
    });
}

Promise.all([funcFour(1), funcFour(0), funcFour(-3)]).then(arr => {
   // got results, some might be null
   console.log(arr);
}).catch(err => {
   // got some error that made it so we couldn't continue
   console.log(err);
});

我知道这是所有风格的观点,但是使用Promise的良好代码的好处之一是,您不再需要使用深度缩进的代码,现在我看到人们放置了各种多余的缩进和行,这些缩进和行根本不需要并且似乎已删除干净承诺编码的一些好处。

在这种情况下, .catch() .then().catch()可以与它们遵循的承诺位于同一行。 并且,无需在新行上开始内联函数定义。

暂无
暂无

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM