我看了一下bluebird承诺常见问题,其中提到。then(成功,失败)是一个反模式。我不太明白它对试捕的解释。 下面有什么问题吗?

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) })

有什么不同?


当前回答

简单的解释:

在ES2018

当使用参数onRejected调用catch方法时, 采取以下步骤: 让承诺成为这份价值。 回报呢?Invoke(promise, "then",«undefined, onRejected»)。

这意味着:

promise.then(f1).catch(f2)

=

promise.then(f1).then(undefiend, f2)

其他回答

好例子,而不是文字。以下代码(如果第一个承诺已解决):

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'); }
)

简单的解释:

在ES2018

当使用参数onRejected调用catch方法时, 采取以下步骤: 让承诺成为这份价值。 回报呢?Invoke(promise, "then",«undefined, onRejected»)。

这意味着:

promise.then(f1).catch(f2)

=

promise.then(f1).then(undefiend, f2)

这两者并不完全相同。不同之处在于,第一个示例不会捕获成功处理程序中抛出的异常。因此,如果您的方法应该只返回已解决的承诺(通常是这种情况),则需要一个尾随catch处理程序(或者另一个带有空成功参数的then)。当然,可能您的then处理程序没有做任何可能失败的事情,在这种情况下,使用一个2参数then可能很好。

但我相信你链接到的文本的观点是,然后是最有用的,而不是回调在它的能力链一堆异步步骤,当你实际上这样做,然后的2参数形式微妙地不像预期的那样表现,出于上述原因。当使用中链时,这尤其违反直觉。

作为一个做过很多复杂的异步工作的人,我真的建议避免这种反模式,使用单独的处理程序方法。

Using .then().catch() lets you enable Promise Chaining which is required to fulfil a workflow. You may need to read some information from database then you want to pass it to an async API then you want to manipulate the response. You may want to push the response back into the database. Handling all these workflows with your concept is doable but very hard to manage. The better solution will be then().then().then().then().catch() which receives all errors in just once catch and lets you keep the maintainability of the code.

通过观察两者的优点和缺点,我们可以计算出哪种适合这种情况。 这是实现承诺的两种主要方法。两者都有优点和缺点

捕捉方法

some_promise_call()
.then(function(res) { logger.log(res) })
.catch(function(err) { logger.log(err) })

优势

所有错误都由一个catch块处理。 Even捕获then块中的任何异常。 多个成功回调的链接

缺点

在链接的情况下,很难显示不同的错误消息。

成功/错误的方法

some_promise_call()
.then(function success(res) { logger.log(res) },
      function error(err) { logger.log(err) })

优势

你得到了细粒度的错误控制。 你可以使用常见的错误处理功能来处理各种类型的错误,比如db错误,500错误等等。

Disavantages

如果希望处理成功回调抛出的错误,仍然需要另一个catch