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 相关文章推荐
用js写了一个类似php的print_r输出换行功能
Feb 18 Javascript
jQuery 属性选择器element[herf*='value']使用示例
Oct 20 Javascript
js父窗口关闭时子窗口随之关闭完美解决方案
Apr 29 Javascript
Jquery 垂直多级手风琴菜单附源码下载
Nov 17 Javascript
JavaScript文档碎片操作实例分析
Dec 12 Javascript
js时间戳转为日期格式的方法
Dec 28 Javascript
JavaScript实现搜索框的自动完成功能(一)
Feb 25 Javascript
js封装成插件_Canvas统计图插件编写实例
Sep 12 Javascript
详解在Vue中使用TypeScript的一些思考(实践)
Jul 06 Javascript
Vue高版本中一些新特性的使用详解
Sep 25 Javascript
Vue实现指令式动态追加小球动画组件的步骤
Dec 18 Vue.js
在JavaScript中如何使用宏详解
May 06 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入门经历和学习过程分享
2014/04/11 PHP
phpmyadmin出现Cannot start session without errors问题解决方法
2014/08/14 PHP
php curl 模拟登录并获取数据实例详解
2016/12/22 PHP
php实现不通过扩展名准确判断文件类型的方法【finfo_file方法与二进制流】
2017/04/18 PHP
php模仿qq空间或朋友圈发布动态、评论动态、回复评论、删除动态或评论的功能(中)
2017/06/11 PHP
Laravel Intervention/image图片处理扩展包的安装、使用与可能遇到的坑详解
2017/11/14 PHP
JS 页面自动加载函数(兼容多浏览器)
2009/05/18 Javascript
jQuery学习笔记之jQuery的动画
2010/12/22 Javascript
JS 控制小数位数的实现代码
2011/08/02 Javascript
解析Jquery取得iframe中元素的几种方法
2013/07/04 Javascript
JQuery创建DOM节点的方法
2015/06/11 Javascript
Jquery使用小技巧汇总
2015/12/29 Javascript
浏览器环境下JavaScript脚本加载与执行探析之动态脚本与Ajax脚本注入
2016/01/19 Javascript
第九篇Bootstrap导航菜单创建步骤详解
2016/06/21 Javascript
详解Node项目部署到云服务器上
2017/07/12 Javascript
vue params、query传参使用详解
2017/09/12 Javascript
详解webpack4升级指南以及从webpack3.x迁移
2018/06/12 Javascript
Cordova(ionic)项目实现双击返回键退出应用
2019/09/17 Javascript
编写Python脚本把sqlAlchemy对象转换成dict的教程
2015/05/29 Python
python实现发送邮件功能
2017/07/22 Python
Python实现基于TCP UDP协议的IPv4 IPv6模式客户端和服务端功能示例
2018/03/22 Python
Python机器学习之scikit-learn库中KNN算法的封装与使用方法
2018/12/14 Python
python生成每日报表数据(Excel)并邮件发送的实例
2019/02/03 Python
python 机器学习之支持向量机非线性回归SVR模型
2019/06/26 Python
使用keras2.0 将Merge层改为函数式
2020/05/23 Python
Python如何实现邮件功能
2020/05/27 Python
英国版MAC彩妆品牌:Illamasqua
2018/04/18 全球购物
世界上最全面的草药补充剂和顶级品牌维生素网站:HerbsPro
2019/01/20 全球购物
Stutterheim瑞典:瑞典高级外套时装品牌
2019/06/24 全球购物
德国、奥地利和瑞士最大的旅行和度假门户网站:HolidayCheck
2019/11/14 全球购物
外语系毕业生求职自荐信
2014/04/12 职场文书
抽样调查项目计划书
2014/04/24 职场文书
《夕阳真美》教学反思
2014/04/27 职场文书
巾帼文明岗汇报材料
2014/12/24 职场文书
数学考试作弊检讨书300字
2015/02/16 职场文书
一些让Python代码简洁的实用技巧总结
2021/08/23 Python