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:你可能不知道的6件事

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件事的更多相关文章

  1. (转)关于 Java 对象序列化您不知道的 5 件事

    关于 Java 对象序列化您不知道的 5 件事 转自:http://developer.51cto.com/art/201506/479979.htm 数年前,当和一个软件团队一起用 Java 语言编 ...

  2. JavaScript中你可能不知道的九件事

    今天凑巧去W3School扫了一遍JavaScript教程,发现从中看到了不少自己曾经没有注意过的细节. 我这些细节列在这里.分享给可能相同不知道的朋友: 1.使用 document.write() ...

  3. 关于 Java Collections API 您不知道的 5 件事,第 1 部分

    定制和扩展 Java Collections Java™ Collections API 远不止是数组的替代品,虽然一开始这样用也不错.Ted Neward 提供了关于用 Collections 做更 ...

  4. 关于 Java 对象序列化您不知道的 5 件事

    数年前,当和一个软件团队一起用 Java 语言编写一个应用程序时,我体会到比一般程序员多知道一点关于 Java 对象序列化的知识所带来的好处. 关于本系列 您觉得自己懂 Java 编程?事实上,大多数 ...

  5. 关于 Java 性能监控您不知道的 5 件事,第 1 部分

    责怪糟糕的代码(或不良代码对象)并不能帮助您发现瓶颈,提高 Java? 应用程序速度,猜测也不能帮您解决.Ted Neward 引导您关注 Java 性能监控工具,从5 个技巧开始,使用Java 5 ...

  6. 关于 Java Collections API 您不知道的 5 件事--转

    第 1 部分 http://www.ibm.com/developerworks/cn/java/j-5things2.html 对于很多 Java 开发人员来说,Java Collections A ...

  7. 关于JavaScripting API您不知道的5件事

    现在,许多 Java 开发人员都喜欢在 Java 平台中使用脚本语言,但是使用编译到 Java 字节码中的动态语言有时是不可行的.在某些情况中,直接编写一个 Java 应用程序的脚本 部分 或者在一个 ...

  8. 关于Java Collections API您不知道的5件事,第2部分

    注意可变对象 java.util 中的 Collections 类旨在通过取代数组提高 Java 性能.如您在 第 1 部分 中了解到的,它们也是多变的,能够以各种方 式定制和扩展,帮助实现优质.简洁 ...

  9. 关于 java.util.concurrent 您不知道的 5 件事--转

    第 1 部分 http://www.ibm.com/developerworks/cn/java/j-5things4.html Concurrent Collections 是 Java™ 5 的巨 ...

随机推荐

  1. Yocto开发笔记之《Tip-bitbake常用命令》(QQ交流群:519230208)

    开了一个交流群,欢迎爱好者和开发者一起交流,转载请注明出处. QQ群:519230208,为避免广告骚扰,申请时请注明 “开发者” 字样 =============================== ...

  2. spring boot 框架 启动更新项目,以及生成 "实体_"文件

    1.更新项目 clean  --->  更新项目 ---> package--->refresh 即可.(这几个步骤一个不能够少) 2.项目中的类的依赖关系存在,但是无法导入依赖 m ...

  3. C# Get/Post 模拟提交

    public static string GetPage(string url, string encoding) { PublicVariables.NetworkConnection = fals ...

  4. HTML5学习预览

    HTML5中,新增了很多input元素的类型 email         email类型用于应该包含 e-mail 地址的输入域. url         url 类型用于应该包含 URL 地址的输入 ...

  5. JAVA 的普通加法运算

    利用Scanner类,其中数字输入的函数,利用while循环结构来得到输入的实数,当输入的是字母时,结束循环 源代码: package ccc;import java.util.*;public cl ...

  6. SortedSet接口

    TreeSet中实现了SortedSet接口,此接口主要用于排序操作,即实现此接口的子类都属于排序的子类. import java.util.Set; import java.util.SortedS ...

  7. 使用Xunit来进行单元测试

    不管你爱与不爱,单元测试对于一个软件的长治久安还是必不可少的一环.在Visual Studio 2012后,VS中的测试浏览器也能与第三方的集成了,用起来还是非常方便的.目前在.Net框架下的测试工具 ...

  8. struts+service+action+数据库

    用户登录流程 1.jsp根据form表单中的action的login   <form action="/test02/login" method="post&quo ...

  9. git diff

    git diff  工作区与暂存区的差别 git diff -cached / git diff -staged  暂存区与版本库的差别 git diff HEAD  工作区与版本库的差别 git d ...

  10. redis缓存分页数据ID

    1.用户通过分类.属性进来分页时 如果没有缓存,就读数据库前10页的数据Id,转为json,根据cate_分类1+cate_分类2+cate_分类3+arr_属性1+arr_属性2+arr_属性3作为 ...