那么在最后的承诺之间有什么区别呢?

finally看到了蓝鸟的文档,但是我还是不太明白与then的差别。

要清楚:我确切地知道为什么thencatch后被调用。 我想让它在被捕之后被调用。 这是意图。 我的问题是:如果我希望代码总是被执行,而不pipepromise的状态如何, then vs finally的区别是什么呢?

我build立了这个testing:

 var Promise = require("bluebird"); function test1 () { console.log("RESOLVE + THEN + CATCH + THEN"); return new Promise((resolve, reject) => resolve()) .then(() => console.log("then")) .catch(err => console.log("error:", err.message)) .then(() => console.log("end")); } function test2 () { console.log("REJECT + THEN + CATCH + THEN"); return new Promise((resolve, reject) => reject(new Error("rejected"))) .then(() => console.log("then")) .catch(err => console.log("error:", err.message)) .then(() => console.log("end")); } function test3 () { console.log("RESOLVE + THEN + CATCH + FINALLY"); return new Promise((resolve, reject) => resolve()) .then(() => console.log("then")) .catch(err => console.log("error:", err.message)) .finally(() => console.log("end")); } function test4 () { console.log("REJECT + THEN + CATCH + FINALLY"); return new Promise((resolve, reject) => reject(new Error("rejected"))) .then(() => console.log("then")) .catch(err => console.log("error:", err.message)) .finally(() => console.log("end")); } // run tests "sequentially" so console output doesn't get blended setTimeout(test1, 500); setTimeout(test2, 1000); setTimeout(test3, 1500); setTimeout(test4, 2000); 

这testing了四种情况:

  1. .then(...).catch(...).then(...).then(...).catch(...).then(...).then(...).catch(...).then(...)和一个已经解决的承诺。
  2. .then(...).catch(...).then(...).then(...).catch(...).then(...)拒绝承诺。
  3. .then(...).catch(...).finally(...)以一个已经解决的承诺。
  4. .then(...).catch(...).finally(...)拒绝承诺。

我看到的结果是1 + 2的情况与3 + 4的情况相同:最后一个位( then或者finally取决于testing)执行,不pipe前面发生了什么。 该程序的输出是:

 RESOLVE + THEN + CATCH + THEN then end REJECT + THEN + CATCH + THEN error: rejected end RESOLVE + THEN + CATCH + FINALLY then end REJECT + THEN + CATCH + FINALLY error: rejected end 

现在,我要问的原因是因为我看到对这个问题的评论 :

不知道你的承诺是否支持它,但你应该改变最后的。然后到最后.then以便busy总是得到清除。

从我then非常有限的知识和上面的testing中,似乎就足够了。 但是,在这个评论之后,我正在质疑自己以及使用它来执行“最终”代码的安全性。

所以我的问题是: thenfinally的区别是什么? 他们看起来像他们的行为一样,但我什么时候需要使用finally而不是呢?

第一个区别:有时你不希望在出现的地方发现错误,但是在使用这个函数的代码中,所以你不要抓住它们。 在这种情况下,你不能用then()finally()来代替。

有时候,你必须清理一下是否有错误(清空引用,清除超时…类似的东西)。 这就是你使用finally()

第二个区别:你传递给catch()的函数也可能抛出,那么你将有一个被拒绝的Promise,下面的then()将不会被调用。

(所以最后一个catch仍然会执行一个错误,不知道)

是的,这就是finally()的要点。 它将在任何情况下执行而不会改变已解决的价值。

你可能想读一遍/ google,关于try {} finally {}

.then.finally不一样。

.then是主要的承诺原始。 这是Promises / A +规范中所定义的,所有承诺库都会实现它。

一个蓝鸟, .finally处理程序将“被调用,而不考虑承诺的命运”。 所以一个未处理的exception仍然会触发。

 new Promise((resolve, reject) => reject(false)) .finally(a => console.log('finally', a)) // finally undefined // Unhandled rejection false new Promise((resolve, reject) => reject(false)) .then(a => console.log('then', a)) // Unhandled rejection false 

.finally不会改变承诺的解决价值,也不会收到承诺链的结果。

 new Promise((resolve, reject) => reject(false)) .catch(e => { console.log(e) return 2 }) .finally(a => { console.log('finally', a) return 1 }) .then(res => console.log('res', res)) // finally undefined // res 2 

在testing用例中,这些方法看起来很相似,因为testing可以捕获所有的错误,而且您只使用承诺进行stream量控制,而不是依赖于承诺链上的parsing/拒绝的值。

好吧,经过KevinB的一番聊天和大量的帮助,我发现至less有一个区别。 考虑以下两个新的testing:

 function test5 () { console.log("REJECT + THEN + CATCH/THROW + THEN"); return new Promise((resolve, reject) => reject(new Error("rejected"))) .then(() => console.log("then")) .catch(function(err) { throw new Error("error in catch"); }) .then(() => console.log("end")); } function test6 () { console.log("REJECT + THEN + CATCH/THROW + FINALLY"); return new Promise((resolve, reject) => reject(new Error("rejected"))) .then(() => console.log("then")) .catch(function(err) { throw new Error("error in catch"); }) .finally(() => console.log("end")); } 

在这些承诺是被拒绝的,但一个错误是从catch

这个承诺最终在两种情况下最终都被拒绝了,但是对于finally情况来说, finally仍然被执行, then就不是。

所以这是不同的。 它们几乎与唯一的例外是相同的,即当从catch处理程序抛出错误时, finally执行, then不执行。

这意味着我引用的评论也有一定的价值:如果在我的error handling程序中发生了另一个错误, then就不能保证清理,但finally会发生。 这是我错过的情况。