在ES2018之前,我曾经在承诺链的末尾嵌套了额外的then
,每当我必须执行任何清理逻辑时,我会在then
和{{{ 1}}以上,例如
catch

但是现在new Promise(
(res, rej) => setTimeout(() => rej({}), 1000)
).then(
res => console.log(res)
).catch(
err => console.error(err)
).then(
() => console.log('Finally')
)
原型上添加了finally
,我无法看到它与上述方法中的上一个Promise
有何不同。以下将产生相同的输出。
then

new Promise(
(res, rej) => setTimeout(() => rej({}), 1000)
).then(
res => console.log(res)
).catch(
err => console.error(err)
).finally(
() => console.log('Finally')
)
仅仅在本机Promise API中用于语义目的吗?
答案 0 :(得分:5)
当承诺被拒绝时,then
回调不会执行 - 即使对于catch
调用返回的承诺,也可能发生这种情况:当其回调抛出或返回被拒绝的承诺时。 err => console.error(err)
可能不会这样做,但你永远不会知道。
同样,如果您只想处理原始承诺中的错误而不是then
回调中的错误,我建议favour .then(…, …)
over .then(…).catch(…)
。我写了
promise.then(console.log, console.error).finally(() => console.log('Finally'));
其他more or less obvious差异在签名中:finally
回调没有收到任何参数,p.finally()
返回的承诺将以相同的结果实现/拒绝作为p
(除非在回调中有异常或返回拒绝)。
答案 1 :(得分:1)
finally()
都会执行。也许MDN doc的例子会有所帮助。
修改:MDN文档提供了与then()
:
finally()
方法与调用.then(onFinally, onFinally)
非常相似,但存在一些差异:
- 创建内联函数时,可以传递一次,而不是强制要求它两次,或者为它创建一个变量
finally
回调不会收到任何争论,因为没有可靠的方法来确定是否履行了承诺或 被拒绝。这个用例适用于您不关心的情况 拒绝原因,或履行价值,所以没有必要 提供它。- 与
Promise.resolve(2).then(() => {}, () => {})
不同(将使用undefined
解决),Promise.resolve(2).finally(() => {})
将通过2
解决。- 同样地,与
Promise.reject(3).then(() => {}, () => {})
不同(将使用undefined
来实现),Promise.reject(3).finally(() => {})
将拒绝3
。