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 相关文章推荐
贴近用户体验的Jquery日期、时间选择插件
Aug 19 Javascript
jQuery Easyui学习之datagrid 动态添加、移除editor
Jan 27 Javascript
javascript创建对象的几种模式介绍
May 06 Javascript
JS简单实现tab切换效果的多窗口显示功能
Sep 07 Javascript
JavaScript实现简易的天数计算器实例【附demo源码下载】
Jan 18 Javascript
解决vue A对象赋值给B对象,修改B属性会影响到A的问题
Sep 25 Javascript
js操作table中tr的顺序实现上移下移一行的效果
Nov 22 Javascript
使vue实现jQuery调用的两种方法
May 12 jQuery
Vue Extends 扩展选项用法完整实例
Sep 17 Javascript
JavaScript键盘事件响应顺序详解
Sep 30 Javascript
Vue filter 过滤器、以及在table中的使用介绍
Sep 07 Javascript
js之ajax文件上传
May 13 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
第七节--类的静态成员
2006/11/16 PHP
PHP exif扩展方法开启详解
2014/07/28 PHP
php中switch与ifelse的效率区别及适用情况分析
2015/02/12 PHP
Javascript的闭包
2009/12/31 Javascript
解析prototype,JQuery中跳出each循环的方法
2013/12/12 Javascript
Javascript实现的常用算法(如冒泡、快速、鸽巢、奇偶等)
2014/04/29 Javascript
快速移动鼠标触发问题及解决方法(ECharts外部调用保存为图片操作及工作流接线mouseenter和mouseleave)
2016/08/29 Javascript
bootstrap table小案例
2016/10/21 Javascript
JS公共小方法之判断对象是否为domElement的实例
2016/11/25 Javascript
Angularjs实现搜索关键字高亮显示效果
2017/01/17 Javascript
微信小程序 下拉列表的实现实例代码
2017/03/08 Javascript
Node.JS更改Windows注册表Regedit的方法小结
2017/08/18 Javascript
Vue中父子组件通讯之todolist组件功能开发
2018/05/21 Javascript
JQuery常见节点操作实例分析
2019/05/15 jQuery
[56:58]VP vs Optic 2018国际邀请赛小组赛BO2 第一场 8.16
2018/08/17 DOTA
[08:06]DOTA2-DPC中国联赛 正赛 PSG.LGD vs Elephant 选手采访
2021/03/11 DOTA
[55:26]DOTA2-DPC中国联赛 正赛 Aster vs LBZS BO3 第一场 2月23日
2021/03/11 DOTA
python实现从ftp服务器下载文件的方法
2015/04/30 Python
python去除文件中重复的行实例
2018/06/29 Python
爬虫代理池Python3WebSpider源代码测试过程解析
2019/12/20 Python
如何基于python操作json文件获取内容
2019/12/24 Python
Python for循环与getitem的关系详解
2020/01/02 Python
pytorch下大型数据集(大型图片)的导入方式
2020/01/08 Python
python实现Pyecharts实现动态地图(Map、Geo)
2020/03/25 Python
使用html5 canvas创建太空游戏的示例
2014/05/08 HTML / CSS
浅析数据存储的三种方式 cookie sessionstorage localstorage 的异同
2020/06/04 HTML / CSS
表达自我的市场:Society6
2018/08/01 全球购物
德国最大的服装、鞋子和配件在线商店之一:Outfits24
2019/07/23 全球购物
汽车运用工程专业毕业生推荐信
2013/12/25 职场文书
城市精细化管理实施方案
2014/03/04 职场文书
劲霸男装广告词改编版
2014/03/21 职场文书
运动会报道稿300字
2014/10/02 职场文书
公安四风对照检查材料思想汇报
2014/10/11 职场文书
旅行社计调工作总结
2015/08/12 职场文书
幼儿园六一儿童节开幕词
2016/03/04 职场文书
2019朋友新婚祝福语精选
2019/10/10 职场文书