那么在最后的承诺之间有什么区别呢?
我finally
看到了蓝鸟的文档,但是我还是不太明白与then
的差别。
要清楚:我确切地知道为什么then
被catch
后被调用。 我想让它在被捕之后被调用。 这是意图。 我的问题是:如果我希望代码总是被执行,而不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了四种情况:
-
.then(...).catch(...).then(...)
,.then(...).catch(...).then(...)
,.then(...).catch(...).then(...)
和一个已经解决的承诺。 -
.then(...).catch(...).then(...)
,.then(...).catch(...).then(...)
拒绝承诺。 -
.then(...).catch(...).finally(...)
以一个已经解决的承诺。 -
.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中,似乎就足够了。 但是,在这个评论之后,我正在质疑自己以及使用它来执行“最终”代码的安全性。
所以我的问题是: then
和finally
的区别是什么? 他们看起来像他们的行为一样,但我什么时候需要使用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
会发生。 这是我错过的情况。