关于Promise:你可能不知道的6件事
FROM ME :
文章介绍了6个Promise的知识点:
1、then() 返回一个 forked Promise(分叉的 Promise):返回的有两种情况;
2、回调函数应该传递结果:在 promise 的上下文中,回调函数像普通的回调函数一样传递结果,返回的结果传给下一个回调函数;
3、只能捕获来自上一级的异常
4、错误能被恢复:在一个错误回调中,如果没有重新抛出错误,promise 会认为你已经恢复了该错误,promise 的状态会转变为 resolved。
5、Promise 能被暂停:为了暂停当前的 promise,或者要它等待另一个 promise 完成,只需要简单地在 then()
函数中返回另一个 promise。
6、resolved 状态的 Promise 不会立即执行
原文:Six Things You Might Not Know About Promises
Promise 是一个非常简单的概念,即使你没有机会使用 Promise,你也可能阅读过一些关于 Promise 的文章。
Promise 的价值在于使得异步代码以一个更可读的风格结构化,而不是因异步函数嵌套显得混乱不堪。这篇文章会接触到 6 个你可能不知道的关于 Promise 的事。
开始列举之前,先看看怎么创建 Promise:
- var p = new Promise(function(resolve, reject) {
- resolve("hello world");
- });
- p.then(function(str) {
- alert(str);
- });
1、then()
返回一个 forked Promise(分叉的 Promise)
下面两段代码有什么不同?
- // Exhibit A
- var p = new Promise(/*...*/);
- p.then(func1);
- p.then(func2);
- // Exhibit B
- var p = new Promise(/*...*/);
- p.then(func1)
- .then(func2);
如果你认为两段代码等价,那么你可能认为 promise 仅仅就是一维回调函数的数组。然而,这两段代码并不等价。p
每次调用 then()
都会返回一个 forked promise。因此,在A中,如果 func1
抛出一个异常,func2
依然能执行,而在B中,func2
不会被执行,因为第一次调用返回了一个新的 promise,由于func1
中抛出异常,这个 promise 被 rejected了,结果 func2
被跳过不执行了。
2、回调函数应该传递结果
下面的代码会 alert 什么?
- var p = new Promise(function(resolve, reject) {
- resolve("hello world");
- });
- p.then(function(str) {})
- .then(function(str) {
- alert(str);
- });
第二个 then()
中的alert不是显示任何东西,因为在 promise 的上下文中,回调函数像普通的回调函数一样传递结果。promise 期望你的回调函数或者返回同一个结果,或者返回其它结果,返回的结果会被传给下一个回调。
这和适配器传递结果的思想一样,看下面的示例:
- var feetToMetres = function(ft) { return ft**0.0254 };
- var p = new Promise(/*...*/);
- p.then(feetToMetres)
- .then(function(metres) {
- alert(metres);
- });
3、只能捕获来自上一级的异常
下面的两段代码有什么不同:
- // Exhibit A
- new Promise(function(resolve, reject) {
- resolve("hello world");
- })
- .then(
- function(str) {
- throw new Error("uh oh");
- },
- undefined
- )
- .then(
- undefined,
- function(error) {
- alert(error);
- }
- );
- // Exhibit B
- new Promise(function(resolve, reject) {
- resolve("hello world");
- })
- .then(
- function(str) {
- throw new Error("uh oh");
- },
- function(error) {
- alert(error);
- }
- );
在A中,当第一个 then
抛出异常时,第二个 then
能捕获到该异常,并会弹出 'uh oh'。这符合只捕获来自上一级异常的规则。
在B中,正确的回调函数和错误的回调函数在同一级,也就是说,尽管在回调中抛出了异常,但是这个异常不会被捕获。事实上,B中的错误回调只有在 promise 被 rejected 或者 promise 自身抛出一个异常时才会被执行。
4、错误能被恢复
在一个错误回调中,如果没有重新抛出错误,promise 会认为你已经恢复了该错误,promise 的状态会转变为 resolved。在下面的例子中,会弹出’I am saved’ 是因为第一个 then()
中的错误回调函数并没有重新抛出异常。
- var p = new Promise(function(resolve,reject){
- reject(new Error('pebkac'));
- });
- p.then(
- undefined,
- function(error){ }
- )
- .then(
- function(str){
- alert('I am saved!');
- },
- function(error){
- alert('Bad computer!');
- }
- );
Promise 可被视为洋葱的皮层,每一次调用 then
都会被添加一层皮层,每一个皮层表示一个能被处理的状态,在皮层被处理之后,promise 会认为已经修复了错误,并准备进入下一个皮层。
5、Promise 能被暂停
仅仅因为你已经在一个 then()
函数中执行过代码,并不意味着你不能够暂停 promise 去做其他事情。为了暂停当前的 promise,或者要它等待另一个 promise 完成,只需要简单地在 then()
函数中返回另一个 promise。
- var = new Promise(/*...*/);
- p.then(function(str){
- if(!loggedIn){
- return new Promise(/*...*/);
- }
- })
- .then(function(str){
- alert("Done!");
- });
在上面的代码中,直到新的 promise 的状态是 resolved解析后,alert 才会显示。如果要在已经存在的异步代码中引入更多的依赖,这是一个很便利的方式。例如,你发现用户会话已经超时了,因此,你可能想要在继续执行后面的代码之前发起第二次登录。
6、resolved 状态的 Promise 不会立即执行
运行下面的代码会弹出什么呢?
- function runme() {
- var i = ;
- new Promise(function(resolve) {
- resolve();
- })
- .then(function() {
- i += ;
- });
- alert(i);
- }
你可能会认为弹出2,因为 promise 已经是 resolved ,then()
会立即执行(同步)。然而,promise 规范要求所有回调都是异步的,因此,alert 执行时 i
的值还没有被修改。
荐读
Promise 的正确打开方式
Promise/A+
Promise 教程
JavaScript Promises 102 - The 4 Promise Methods
关于Promise:你可能不知道的6件事的更多相关文章
- (转)关于 Java 对象序列化您不知道的 5 件事
关于 Java 对象序列化您不知道的 5 件事 转自:http://developer.51cto.com/art/201506/479979.htm 数年前,当和一个软件团队一起用 Java 语言编 ...
- JavaScript中你可能不知道的九件事
今天凑巧去W3School扫了一遍JavaScript教程,发现从中看到了不少自己曾经没有注意过的细节. 我这些细节列在这里.分享给可能相同不知道的朋友: 1.使用 document.write() ...
- 关于 Java Collections API 您不知道的 5 件事,第 1 部分
定制和扩展 Java Collections Java™ Collections API 远不止是数组的替代品,虽然一开始这样用也不错.Ted Neward 提供了关于用 Collections 做更 ...
- 关于 Java 对象序列化您不知道的 5 件事
数年前,当和一个软件团队一起用 Java 语言编写一个应用程序时,我体会到比一般程序员多知道一点关于 Java 对象序列化的知识所带来的好处. 关于本系列 您觉得自己懂 Java 编程?事实上,大多数 ...
- 关于 Java 性能监控您不知道的 5 件事,第 1 部分
责怪糟糕的代码(或不良代码对象)并不能帮助您发现瓶颈,提高 Java? 应用程序速度,猜测也不能帮您解决.Ted Neward 引导您关注 Java 性能监控工具,从5 个技巧开始,使用Java 5 ...
- 关于 Java Collections API 您不知道的 5 件事--转
第 1 部分 http://www.ibm.com/developerworks/cn/java/j-5things2.html 对于很多 Java 开发人员来说,Java Collections A ...
- 关于JavaScripting API您不知道的5件事
现在,许多 Java 开发人员都喜欢在 Java 平台中使用脚本语言,但是使用编译到 Java 字节码中的动态语言有时是不可行的.在某些情况中,直接编写一个 Java 应用程序的脚本 部分 或者在一个 ...
- 关于Java Collections API您不知道的5件事,第2部分
注意可变对象 java.util 中的 Collections 类旨在通过取代数组提高 Java 性能.如您在 第 1 部分 中了解到的,它们也是多变的,能够以各种方 式定制和扩展,帮助实现优质.简洁 ...
- 关于 java.util.concurrent 您不知道的 5 件事--转
第 1 部分 http://www.ibm.com/developerworks/cn/java/j-5things4.html Concurrent Collections 是 Java™ 5 的巨 ...
随机推荐
- C#------各种常见错误解决方法
1.错误:模型生成过程中检测到一个或多个验证错误 表示实体中的数据列没有和SQLServer数据库里面的表中的数据列完全相同,比如SQLServer中有ID,Name,Post,那么实体中也应该有ID ...
- BIOS设置第一启动项
在电脑的Bois中怎样去设置第一启动项.. 对于很多新手朋友来说,BIOS满屏英文,生涩难懂,话说我原来也很排斥BIOS,界面太丑,光看界面就没什么兴趣,更谈不上深入研究,大多数人在电脑城装机的时候都 ...
- 自然语言6_treebank句子解析
#英文句子结构分析 import nltkfrom nltk.corpus import treebankt = treebank.parsed_sents('wsj_0001.mrg')[1]t.d ...
- mvc-1
- docker快速搭建wordpress(centos7)
docker pull tutum/wordpress #拉取镜像 docker run -d -p 80:80 tutum/wordpress #运行容器 使用服务器IP访问即可
- Django开发web环境搭建的简单方法(CentOS6.5环境)
这几天跟Linux下的Python + Django环境搭建卯上了.经过几天的琢磨,找到了一条自己认为给力的路径. 这里给出命令行,过程如下: 首次登陆,切换管理员: [web@bogon ~]$ s ...
- Effective Objective-C 2.0 — 第13条:用“方法调配 技术” 调试 “黑盒方法”
自己理解是调配了方法 在运行期,可以向类中新增或替换选择子所对应的方法实现. 使用另一份实现来替换原有的方法实现,这道工序叫做“方法调配”,开发者常用此技术向原有实现中添加新功能. 一般来说,只有调试 ...
- Spring系列之beanFactory与ApplicationContext
一.BeanFactoryBeanFactory 是 Spring 的“心脏”.它就是 Spring IoC 容器的真面目.Spring 使用 BeanFactory 来实例化.配置和管理 Bean. ...
- mybatis map foreach遍历
mybatis map foreach遍历 转至http://www.cnblogs.com/yg_zhang/p/4314602.html mybatis 遍历map实例 map 数据如下 Map& ...
- vim中添加molokai.vim 配色安装
无意中发现知乎中讨论的话题: 你认为最好看的 Vim 配色方案(color scheme)是哪款? 网友回答 排在第一位的是:molokai 啊,最经典的配色 既然molokai这么经典,当然要用了. ...