Promise.then(a, b) 和 Promise.then(a).catch(b) 一样吗? [复制]

Posted

技术标签:

【中文标题】Promise.then(a, b) 和 Promise.then(a).catch(b) 一样吗? [复制]【英文标题】:Is Promise.then(a, b) the same as Promise.then(a).catch(b)? [duplicate] 【发布时间】:2019-01-12 12:34:19 【问题描述】:

两者有什么区别

myPromise.then(a, b)
myPromise.then(a).catch(b)

?

无论myPromise 的内容和状态以及ab 的函数实现如何,这两个javascript 表达式是否总是产生相同的结果?

除了代码可读性之外,我是否更喜欢使用其中一种?

【问题讨论】:

【参考方案1】:

它们在处理 then() 回调中的错误的方式上有所不同,在某些情况下,这可能是一个足够大的差异,大多数人建议仅使用 catch()

例如使用catch(),您可以捕获此错误:

Promise.resolve('test')
.then(r => 
  throw("whoops")
)
.catch(e => console.log("caught error:", e))

不能使用then(a,b) 样式:

Promise.resolve('test')
.then(r =>  throw("whoops"),
      e => console.log("caught error?", e))
// unhandled rejection (you'll need to look in the console)

除了一些测试场景之外,很难想到会首选这种行为的用例。

您可以同时使用这两种方法,这将在then() 回调中捕获拒绝和错误,但这会使事情变得比您可能需要的更加混乱,除非您有一个特殊的用例来区分这两种错误。例如哪个处理程序处理哪些错误:

Promise.reject("rejected")
.then(r => throw("whoops"), 
     e => console.log("Promise 1: caught error in second function:", e))
.catch(e=> console.log("Promise 1: caught error in catch", e))

Promise.resolve("rejected")
.then(r => throw("whoops"), 
     e => console.log("Promise 2: caught error in second function:", e))
.catch(e=> console.log("Promise 2: caught error in catch", e))

【讨论】:

实际上,想要处理来自某个 Promise 的拒绝是很常见的,不仅仅是“一些测试场景”。 我非常喜欢这个答案,它很好地展示了两种情况之间的差异。谢谢!【参考方案2】:

推荐使用catch(),因为当我们在一个promise链中使用myPromise.then(a, b)时,即使promise被拒绝,next then block也会一直执行。这是因为承诺链认为我们已经清除了错误处理程序中的错误。 看下面的例子: 即使我们reject() 下一个 then 块也会执行。

function asyncFun(a,b)
  return new Promise((resolve, reject)=>
      if(typeof a ==="number" && typeof b === "number")
        resolve(a + b);
      else
        reject("invalid data!!");
  );

asyncFun(2,'4').then((response)=>
  console.log(response);
  return response;
, (error)=>
  console.log(error);
).then((response)=>
  console.log("console 2",response)
, (error)=>
  console.log(error);
);

虽然如果我们在 Promise 链的末尾仅使用单个错误处理程序 catch(),则不会发生这种情况:请注意正如 Bergi 指出的那样,即使在多个 catch() 的情况下也会重现上述场景。

function asyncFun(a,b)
  return new Promise((resolve, reject)=>
      if(typeof a ==="number" && typeof b === "number")
        resolve(a + b);
      else
        reject("invalid data!!");
  );

asyncFun(2,'4').then((response)=>
  console.log(response);
  return response;
).then((response)=>
  console.log("console 2",response)
).catch((err)=> console.log(err));

【讨论】:

建议您在需要时使用.catch(),但并非总是如此。 @Ry- 更新了答案,谢谢:-) 你的例子没有意义:即使你使用了两个catch 块,下一个then 回调也会被执行。这里的修复是删除一个错误处理程序,而不是使用不同的then 语法。不,正如@Ry- 所说:一般不建议使用catch 那么你想说的是,如果第一个then() 块只有一个参数,并且承诺被拒绝,那么第二个then(func) 块会被跳过吗?如果是这样,我认为它可以有更好的措辞,但无论如何感谢你为我指明了正确的方向!【参考方案3】:

我认为这两种方式是相同的。但是,我更喜欢使用async().then().catch(),因为它更容易阅读。

此外,如果您想一一调用一些异步函数,但如果抛出一些错误需要立即中断(不希望以下函数继续运行)。您只需要在决赛中放 1 个接球即可。在这种情况下,我们不能使用第一种样式。

asyncA()
    .then((val) => asyncB(val))
    .then((val) => asyncC(val))
    .then((val) => asyncD(val))
    .catch(() =>  /* any of asyncA, asyncB, asyncC, asyncD will goes directly here if throwing error )

在上面的例子中。可以看到,任何一个函数async失败,程序都会跳过后面的函数直接catch。

【讨论】:

它们不一样。 怎么不一样?你可以用一种风格举个例子,我可以用另一种风格解决它,结果和你预期的一样。 该问题询问p.then(a, b)p.then(a).catch(b) 之间的区别。就是这样,这就是全部。用“我认为这两种方式是相同的”来回答它是错误的。请参阅投票赞成的答案,了解它们有何不同。 我回答了一般用法都差不多。区别在于编码风格。而且我还陈述了我认为只能应用 catch() 的唯一情况。那么你还想要什么? 这不是优化。行为上有一个实际而重要的区别。

以上是关于Promise.then(a, b) 和 Promise.then(a).catch(b) 一样吗? [复制]的主要内容,如果未能解决你的问题,请参考以下文章

js es6 promise 中 resolve 如何传递多个参数?

Promise.then方法的返回值问题

09 promise then

如何对 AngularJS $promise.then 进行单元测试

Promise.then() 在 promise 解决之前执行

如果使用 then ,是不是需要在 promise 中嵌套 catch?