我查看了bluebird promise FAQ,其中提到.then(success, fail)
is an antipattern。我不太了解它对try和catch的解释。
以下是什么问题?
some_promise_call()
.then(function(res) { logger.log(res) }, function(err) { logger.log(err) })
似乎这个例子暗示了以下正确的方法。
some_promise_call()
.then(function(res) { logger.log(res) })
.catch(function(err) { logger.log(err) })
有什么区别?
答案 0 :(得分:183)
有什么区别?
.then()
调用将返回一个承诺,如果回调引发错误,将拒绝承诺。这意味着,当您的成功logger
失败时,错误将传递给以下.catch()
回调,而不会传递给与fail
并列的success
回调。
这是控制流程图表:
用同步代码表达:
// some_promise_call().then(logger.log, logger.log)
then: {
try {
var results = some_call();
} catch(e) {
logger.log(e);
break then;
} // else
logger.log(results);
}
第二个log
(就像.then()
的第一个参数)只会在没有发生异常的情况下执行。标记的块和break
语句感觉有点奇怪,这实际上是python has try-except-else
for(推荐阅读!)。
// some_promise_call().then(logger.log).catch(logger.log)
try {
var results = some_call();
logger.log(results);
} catch(e) {
logger.log(e);
}
catch
记录器还将处理成功记录器调用中的异常。
差异很大。
我不太了解它对try和catch的解释
争论的焦点是,您通常希望在处理的每个步骤中捕获错误,并且您不应该在链中使用它。期望是你只有一个处理所有错误的最终处理程序 - 而当你使用"反模式"时,一些后面回调中的错误不会被处理。
但是,这种模式实际上非常有用:当您想要处理恰好在此步骤中发生的错误,并且您希望在没有错误发生时执行完全不同的 - 即错误是不可恢复的。 请注意这是分支您的控制流程。当然,这有时是需要的。
以下是什么问题?
some_promise_call() .then(function(res) { logger.log(res) }, function(err) { logger.log(err) })
你必须重复你的回调。你想要
some_promise_call()
.catch(function(e) {
return e; // it's OK, we'll just log it
})
.done(function(res) {
logger.log(res);
});
您也可以考虑使用.finally()
。
答案 1 :(得分:32)
这两者并不完全相同。不同之处在于第一个示例不会捕获在success
处理程序中抛出的异常。因此,如果您的方法应该只返回已解决的promise,那么通常就是这种情况,您需要一个尾随的catch
处理程序(或另一个then
具有空success
参数的处理程序。当然,可能是你的then
处理程序没有做任何可能失败的事情,在这种情况下使用一个双参数then
可能没问题。
但是我相信你所链接的文本的意思是then
对于链接一系列异步步骤的能力而言最有用,而当你实际执行此操作时,它的2参数形式由于上述原因,then
巧妙地表现得并不像预期的那样。当使用中链时,它特别违反直觉。
作为一个做了很多复杂异步事情的人并且碰到了这样的角落,而不是我承认,我真的建议避免使用这种反模式并使用单独的处理程序方法。
答案 2 :(得分:17)
通过观察两者的优点和缺点,我们可以对哪种情况做出适当的猜测。 这是实施承诺的两种主要方法。两者都有它的优缺点
捕捉方法
some_promise_call()
.then(function(res) { logger.log(res) })
.catch(function(err) { logger.log(err) })
<强>优点强>
<强>缺点强>
成功/错误方法
some_promise_call()
.then(function success(res) { logger.log(res) },
function error(err) { logger.log(err) })
<强>优点强>
<强> Disavantages 强>
catch
答案 3 :(得分:0)
简单的解释:
在ES2018中
使用参数onRejected调用catch方法时, 采取以下步骤:
- 让诺就是这个价值。
- 返回?调用(承诺,“然后”,«未定义,onRejected»)。
这意味着:
promise.then(f1).catch(f2)
等于
promise.then(f1).then(undefiend, f2)
答案 4 :(得分:0)
使用.then().catch()
可启用实现工作流程所需的承诺链接。您可能需要从数据库中读取一些信息,然后将其传递给异步API,然后才能处理响应。您可能需要将响应推回数据库。用您的概念来处理所有这些工作流是可行的,但很难管理。更好的解决方案是then().then().then().then().catch()
,它一次捕获所有错误,并让您保持代码的可维护性。
答案 5 :(得分:0)
使用then()
和catch()
有助于在诺言上链接成功和失败处理程序。catch()
在then()
返回的诺言上起作用。它可以处理
then()
上的失败回调无法处理。)
1. let promiseRef: Promise = this. aTimetakingTask (false);
2. promiseRef
3. .then(
4. (result) => {
5. /* successfully, resolved promise.
6. Work on data here */
7. },
8. (error) => console.log(error)
9. )
10. .catch( (e) => {
11. /* successfully, resolved promise.
12. Work on data here */
13. });
注意:很多时候,如果
catch()
为 已经写了。 编辑:reject()
仅在发生错误时才导致调用catch()
{strong>未中未定义then()
中的处理程序。注意图片中的#3catch()
。当第8行和第9行中的处理程序不在时调用 定义。
这是有道理的,因为由then()
返回的promise如果进行回调时不会出错。
答案 6 :(得分:-1)
而不是言语,好榜样。以下代码(如果第一个承诺已解决):
Promise.resolve()
.then
(
() => { throw new Error('Error occurs'); },
err => console.log('This error is caught:', err)
);
与:
相同Promise.resolve()
.catch
(
err => console.log('This error is caught:', err)
)
.then
(
() => { throw new Error('Error occurs'); }
)
但是,如果拒绝了第一个承诺,那就不一样了:
Promise.reject()
.then
(
() => { throw new Error('Error occurs'); },
err => console.log('This error is caught:', err)
);
Promise.reject()
.catch
(
err => console.log('This error is caught:', err)
)
.then
(
() => { throw new Error('Error occurs'); }
)