查看原文
其他

【第663期】关于Promise:你可能不知道的6件事

2016-08-06 会飞的Pikachu 前端早读课

前言

不知道为什么,这周突然过的非常快,又到周末了。然在本周由于在开发团队小应用的时候“入门”了mongoose,一个页面多模块输出那么这一下子又涉及到promise了。所以今天的文章就是由@会飞的Pikachu带来的翻译。


正文从这开始~


Promise 是一个非常简单的概念,即使你没有机会使用 Promise,你也可能阅读过一些关于 Promise 的文章。


Promise 的价值在于使得异步代码以一个更可读的风格结构化,而不是因异步函数嵌套显得混乱不堪。这篇文章会接触到 6 个你可能不知道的关于 Promise 的事。


开始列举之前,先看看怎么创建 Promise:



1、then() 返回一个 forked Promise(分叉的 Promise)

下面两段代码有什么不同?


如果你认为两段代码等价,那么你可能认为 promise 仅仅就是一维回调函数的数组。然而,这两段代码并不等价。p 每次调用 then() 都会返回一个 forked promise。因此,在A中,如果 func1 抛出一个异常,func2 依然能执行,而在B中,func2 不会被执行,因为第一次调用返回了一个新的 promise,由于 func1 中抛出异常,这个 promise 被 rejected了,结果 func2 被跳过不执行了。


2、回调函数应该传递结果

下面的代码会 alert 什么?


第二个 then() 中的alert不是显示任何东西,因为在 promise 的上下文中,回调函数像普通的回调函数一样传递结果。promise 期望你的回调函数或者返回同一个结果,或者返回其它结果,返回的结果会被传给下一个回调。


这和适配器传递结果的思想一样,看下面的示例:



3、只能捕获来自上一级的异常

下面的两段代码有什么不同:


在A中,当第一个 then 抛出异常时,第二个 then 能捕获到该异常,并会弹出 'uh oh'。这符合只捕获来自上一级异常的规则。


在B中,正确的回调函数和错误的回调函数在同一级,也就是说,尽管在回调中抛出了异常,但是这个异常不会被捕获。事实上,B中的错误回调只有在 promise 被 rejected 或者 promise 自身抛出一个异常时才会被执行。


4、错误能被恢复

在一个错误回调中,如果没有重新抛出错误,promise 会认为你已经恢复了该错误,promise 的状态会转变为 resolved。在下面的例子中,会弹出’I am saved’ 是因为第一个 then() 中的错误回调函数并没有重新抛出异常。


Promise 可被视为洋葱的皮层,每一次调用 then 都会被添加一层皮层,每一个皮层表示一个能被处理的状态,在皮层被处理之后,promise 会认为已经修复了错误,并准备进入下一个皮层。


5、Promise 能被暂停

仅仅因为你已经在一个 then() 函数中执行过代码,并不意味着你不能够暂停 promise 去做其他事情。为了暂停当前的 promise,或者要它等待另一个 promise 完成,只需要简单地在 then() 函数中返回另一个 promise。


在上面的代码中,直到新的 promise 的状态是 resolved解析后,alert 才会显示。如果要在已经存在的异步代码中引入更多的依赖,这是一个很便利的方式。例如,你发现用户会话已经超时了,因此,你可能想要在继续执行后面的代码之前发起第二次登录。


6、resolved 状态的 Promise 不会立即执行

运行下面的代码会弹出什么呢?


你可能会认为弹出2,因为 promise 已经是 resolved ,then() 会立即执行(同步)。然而,promise 规范要求所有回调都是异步的,因此,alert 执行时 i 的值还没有被修改。


最后,作者曾经还发布过:

【第502期】编写高质量JavaScript代码的一些建议


关于promise的主题,曾经有过:

【第553期】Promise 陷阱

【第519期】Promise与异步


关于本文

译者:@会飞的Pikachu

译文链接:https://github.com/dwqs/blog/issues/1


欢迎投稿到前端早读课

投稿邮箱:181422448@qq.com

您可能也对以下帖子感兴趣

文章有问题?点此查看未经处理的缓存