We read every piece of feedback, and take your input very seriously.
To see all available qualifiers, see our documentation.
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
Promise已经像血液一样融入到我们的日常工作中,thenable无时无刻不在发挥着它的作用。网络上关于Promise的文章也是汗牛充栋,人们一遍又一遍的咀嚼着Promise.prototype.then, Promise.prototype.catch的作用和功效。
很多时候,我们的执行函数会是p.then(onFulfilled).catch(onRejected)这种形式,并不会链接太多操作,这有点像try语句。
有时候,我们希望一个操作,无论是否抛出异常都会执行,即不管它进入了resolve,还是reject,下一步操作都会执行。比如我们发送请求之前会出现一个loading图,当我们请求发送完成之后,不管请求有没有出错,我们都希望关掉这个loading图以提升用户体验。过去我们可以这么做:
this.loading = true request() .then((res) => { // do something this.loading = false }) .catch(() => { // log err this.loading = false })
这种写法一点也不DRY,显得丑陋。为了让代码稍微好看一点,我们也可以这么写:
this.loading = true request() .then((res) => { // do something }) .catch(() => { // log err }) .then(() => { this.loading = false })
这么写虽然让我们舒服了点,但是,总感觉哪里怪怪的,总觉得.then后面还有.catch。作为类比,我们可以看一下try语句的三种声明形式:
那么问题来了,为什么Promise没有实现finally的写法,用于在任何情况下(不论成功或者失败)执行特定后续操作。这样在语义上,代码显得更加直观与合理。
好消息是,Promise.prototype.finally已于2018/01/24进入ES8的stage4阶段。半数以上的浏览器也做出了兼容。我们现在就可以尝鲜使用了。
于是上面的例子就变成了这样:
this.loading = true request() .then((res) => { // do something }) .catch(() => { // log err }) .finally(() => { this.loading = false })
看起来好像也没有什么区别,但其实使用Promise.finally(onFinally) 和 Promise.then(onFulfilled, onRejected)还是有以下几点不同:
1、2两点容易理解,至于3、4,可以通过下面的两个例子进行说明:
Promise.resolve('foo'). finally(() => 'bar'). then(res => console.log(res)); Promise.reject(new Error('foo')). finally(() => 'bar'). catch(err => console.log(err.message)); // 最终打印的是‘foo’而不是‘bar',因为finally()会透传fullfilled的值和rejected错误
如果浏览器没有实现finally,那么可以实现polyfill:
if (typeod Promise.prototype.done !== 'function') { Promise.prototype.finally = function(onFinally) { return this.then( /* onFulfilled */ res => Promise.resolve(onFinally()).then(() => res), /* onRejected */ err => Promise.resolve(onFinally()).then(() => { throw err; }) ); }; }
通过该polyfill,可以更加理解为什么finally()会透传fullfilled的值和rejected错误。
Promise.prototype.finally()会返回一个promise对象,Promise chain会延续下去。但是如果我们不想这条Promise chain继续执行下去,而想在执行一个操作后关闭Promise chain。这种时候就需要用到Promise.prototype.done().
Promise.prototype.done的使用方法和then一样,但是该方法不会返回Promise对象。
实现Promise.prototype.done的polyfill如下:
if (typeof Promise.prototype.done === 'undefined') { Promise.prototype.done = function (onFulfilled, onRejected) { this.then(onFulfilled, onRejected).catch(function (error) { setTimeout(function () { throw error; }, 0); }); }; }
可以看到,Promise.prototype.done和Promise.prototype.finally存在两点不同:
由于Promise的try-catch机制,出错的问题可能会被内部消化掉。 如果在调用的时候每次都无遗漏的进行 catch 处理的话当然最好了,但是如果在实现的过程中出现了这个例子中的错误的话,那么进行错误排除的工作也会变得困难。这种错误被内部消化的问题也被称为 unhandled rejection ,从字面上看就是在Rejected时没有找到相应处理的意思。 - promise迷你书
以上便是Promise.prototype.finally和Promise.prototype.done的介绍和说明,也许实际使用的频率不会很高,但是为了高可读的代码,大家不妨一试。 (ゝ∀・)
The text was updated successfully, but these errors were encountered:
auto-archiving for issue #256
22a6efa
promise.finally 的回调为毛要用 Promise.resolve(fun()).then(() => value) 这样的方式进行处理,直接 fun(); return value 不是一样的吗?
Sorry, something went wrong.
88行
if (typeod Promise.prototype.done !== 'function') { Promise.prototype.finally = function(onFinally) { ...
应该是
if (typeod Promise.prototype.finally !== 'function') { Promise.prototype.finally = function(onFinally) { ...
No branches or pull requests
Promise已经像血液一样融入到我们的日常工作中,thenable无时无刻不在发挥着它的作用。网络上关于Promise的文章也是汗牛充栋,人们一遍又一遍的咀嚼着Promise.prototype.then, Promise.prototype.catch的作用和功效。
很多时候,我们的执行函数会是p.then(onFulfilled).catch(onRejected)这种形式,并不会链接太多操作,这有点像try语句。
有时候,我们希望一个操作,无论是否抛出异常都会执行,即不管它进入了resolve,还是reject,下一步操作都会执行。比如我们发送请求之前会出现一个loading图,当我们请求发送完成之后,不管请求有没有出错,我们都希望关掉这个loading图以提升用户体验。过去我们可以这么做:
这种写法一点也不DRY,显得丑陋。为了让代码稍微好看一点,我们也可以这么写:
这么写虽然让我们舒服了点,但是,总感觉哪里怪怪的,总觉得.then后面还有.catch。作为类比,我们可以看一下try语句的三种声明形式:
那么问题来了,为什么Promise没有实现finally的写法,用于在任何情况下(不论成功或者失败)执行特定后续操作。这样在语义上,代码显得更加直观与合理。
好消息是,Promise.prototype.finally已于2018/01/24进入ES8的stage4阶段。半数以上的浏览器也做出了兼容。我们现在就可以尝鲜使用了。
于是上面的例子就变成了这样:
看起来好像也没有什么区别,但其实使用Promise.finally(onFinally) 和 Promise.then(onFulfilled, onRejected)还是有以下几点不同:
1、2两点容易理解,至于3、4,可以通过下面的两个例子进行说明:
如果浏览器没有实现finally,那么可以实现polyfill:
通过该polyfill,可以更加理解为什么finally()会透传fullfilled的值和rejected错误。
Promise.prototype.finally()会返回一个promise对象,Promise chain会延续下去。但是如果我们不想这条Promise chain继续执行下去,而想在执行一个操作后关闭Promise chain。这种时候就需要用到Promise.prototype.done().
Promise.prototype.done的使用方法和then一样,但是该方法不会返回Promise对象。
实现Promise.prototype.done的polyfill如下:
可以看到,Promise.prototype.done和Promise.prototype.finally存在两点不同:
以上便是Promise.prototype.finally和Promise.prototype.done的介绍和说明,也许实际使用的频率不会很高,但是为了高可读的代码,大家不妨一试。 (ゝ∀・)
参考
The text was updated successfully, but these errors were encountered: