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
的内容和状态以及a
和b
的函数实现如何,这两个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 如何传递多个参数?
如何对 AngularJS $promise.then 进行单元测试