JavaScript异步编程Promise模式的6个特性


Posted in Javascript onApril 03, 2014

在我们开始正式介绍之前,我们想看看Javascript Promise的样子:

var p = new Promise(function(resolve, reject) {
  resolve("hello world");
});p.then(function(str) {
  alert(str);
});

1. then()返回一个Forked Promise

以下两段代码有什么区别呢?

// Exhibit A
var p = new Promise(/*...*/);
p.then(func1);
p.then(func2);// Exhibit B
var p = new Promise(/*...*/);
p.then(func1)
.then(func2);

如果你认真以上两段代码等同的话,那么Promises只不过是一个一维的回调函数数组。然而,其实不是这样的。每一个then()调用都返回一个forked promise。因此,ExhibitA中,如果func1()抛出一个异常,func2()仍旧正常调用。

在ExhibitB中,如果func1()抛出一个错误,fun2()将不会被调用,因为第一个调用返回了一个新的promise,这个在func1()中会被拒绝。结果是func2()被跳过。

总结:promises可以被fork成多个路径,类似复杂的流程图。

2. Callback应该传递结果

当你运行下面代码的时候什么会得到警告提示呢?

var p = new Promise(function(resolve, reject) {
  resolve("hello world");
});p.then(function(str) {})
.then(function(str) {
  alert(str);
});

第二个then()中的alert没有显示任何内容。这是因为回调函数,在promise的上下文中,因为结果的变化并没有回调函数。promise期望你的回调函数返回同样的结果或者返回一个替换结果,然后被传递到下一个回调函数中。

类似使用adpater来变化结果,如下:

var feetToMetres = function(ft) { return ft*12*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);
  }
);

在第一段代码中,在第一个then()中的异常被抛出,将会被第二个then()捕捉,然后“uh oh”警告将会被触发。这个遵循只有前一个层次的异常会被捕捉。

在第二段代码中,回调函数和错误回调函数是同一个层次,意味着当异常在回调中抛出,将不会被捕捉。事实上,第二段代码的错误回调将只会在promise为拒绝状态或者promise本身出错的情况下抛出

4. 错误可以被恢复

在一个错误回调函数中,如果你不重新抛出错误,promise会假设你已经从错误中恢复,并且反转成为已解决状态。在下一个例子中,"i'm 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()添加另外一个层次到洋葱上。每一个层次代表了一个被处理的活动。当层次结束,结果被认为已经修复并且为下一个层次做好了准备。

5. Promises可以被暂停

因为你已经准备好了在一个then()方法中执行,并不意味着你不能够暂停并且提前运行其他。 为了暂停目前的promise,或者让它等待以便另外一个promise完成,简单在then()中返回另外一个promise。

var p = new Promise(/*...*/);p.then(function(str) {
  if(!loggedIn) {
    return new Promise(/*...*/);
  }
})
.then(function(str) {
  alert("Done.");
})

在前面代码中,直到新的promise解析后提示才会出现。这是一个方便的方式在已存在的异步代码路径中来引入更多地依赖。例如,你可能发现用户session已经timeout,并且你可能希望在继续前面的代码路径前初始化第二个登陆。

6. Resolved Promises并不会立刻执行

运行下面代码会得到提示框么?

function runme() {
  var i = 0;  new Promise(function(resolve) {
    resolve();
  })
  .then(function() {
    i += 2;
  });
  alert(i);
}

因为promise被立刻解析,然后then()方法被立刻执行,所以你可能会认为会探出提示2。但是promise定义要求所有的调用都被强制异步。因此提示会在被修改前生成。
Javascript 相关文章推荐
HTML node相关的一些资料整理
Jan 01 Javascript
Javascript单元测试框架QUnitjs详细介绍
May 08 Javascript
JS完整获取IE浏览器信息包括类型、版本、语言等等
May 22 Javascript
jquery 取子节点及当前节点属性值
Jul 25 Javascript
js显示当前日期时间和星期几
Oct 22 Javascript
纯原生js实现table表格的增删
Jan 05 Javascript
浅谈微信小程序之官方UI框架we-ui使用教程
Aug 20 Javascript
Vue 刷新当前路由的实现代码
Sep 26 Javascript
js实现九宫格抽奖
Mar 19 Javascript
vue-autoui自匹配webapi的UI控件的实现
Mar 20 Javascript
Nuxt.js 静态资源和打包的操作
Nov 06 Javascript
javascript实现左右缓动动画函数
Nov 25 Javascript
document.compatMode的CSS1compat使用介绍
Apr 03 #Javascript
javascript实现des解密加密全过程
Apr 03 #Javascript
无刷新预览所选择的图片示例代码
Apr 02 #Javascript
jQuery防止click双击多次提交及传递动态函数或多参数
Apr 02 #Javascript
jquery跟js初始化加载的多种方法及区别介绍
Apr 02 #Javascript
jquery中子元素和后代元素的区别示例介绍
Apr 02 #Javascript
js 日期比较相关天数代码
Apr 02 #Javascript
You might like
一贴学会PHP 新手入门教程
2009/08/03 PHP
php cli 小技巧
2013/06/03 PHP
smarty内置函数{loteral}、{ldelim}和{rdelim}用法实例
2015/01/22 PHP
PHP Hash算法:Times33算法代码实例
2015/05/13 PHP
关于php 高并发解决的一点思路
2017/04/16 PHP
PHP实现对xml的增删改查操作案例分析
2017/05/19 PHP
thinkphp5.1框架中容器(Container)和门面(Facade)的实现方法分析
2019/08/05 PHP
基于jQuery的弹出消息插件 DivAlert之旅(一)
2010/04/01 Javascript
js特殊字符转义介绍
2013/11/05 Javascript
用js+iframe形成页面的一种遮罩效果的具体实现
2013/12/31 Javascript
浅谈javascript 函数属性和方法
2015/01/21 Javascript
jQuery form 表单验证插件(fieldValue)校验表单
2016/01/24 Javascript
去除html代码里面的script正则方法
2016/05/19 Javascript
bootstrap table实现x-editable的行单元格编辑及解决数据Empty和支持多样式问题
2017/08/10 Javascript
JavaScript面向对象精要(上部)
2017/09/12 Javascript
详解vuex之store拆分即多模块状态管理(modules)篇
2018/11/13 Javascript
JavaScript基于遍历操作实现对象深拷贝功能示例
2019/03/05 Javascript
高效jQuery选择器的5个技巧实例分析
2019/11/26 jQuery
node.js爬虫框架node-crawler初体验
2020/10/29 Javascript
初步剖析C语言编程中的结构体
2016/01/16 Python
Python面向对象class类属性及子类用法分析
2018/02/02 Python
Django如何防止定时任务并发浅析
2019/05/14 Python
python算法与数据结构之冒泡排序实例详解
2019/06/22 Python
python项目对接钉钉SDK的实现
2019/07/15 Python
Python 切分数组实例解析
2019/11/07 Python
关于ZeroMQ 三种模式python3实现方式
2019/12/23 Python
tensorflow 环境变量设置方式
2020/02/06 Python
PyCharm 专业版安装图文教程
2020/02/20 Python
Python API len函数操作过程解析
2020/03/05 Python
使用CSS3来匹配横屏竖屏的简单方法
2015/08/04 HTML / CSS
应届生护士求职信
2013/11/01 职场文书
工商企业管理实习自我鉴定
2013/12/04 职场文书
文员岗位职责范本
2014/03/08 职场文书
庆国庆国旗下讲话稿2014
2014/09/21 职场文书
八项规定自查自纠报告及整改措施
2014/10/26 职场文书
Python实现8种常用抽样方法
2021/06/27 Python