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 相关文章推荐
PNGHandler-借助JS让PNG图在IE下实现透明(包括背景图)
Aug 31 Javascript
基于Jquery实现表格动态分页实现代码
Jun 21 Javascript
jQuery+HTML5实现手机摇一摇换衣特效
Jun 05 Javascript
jquery插件splitScren实现页面分屏切换模板特效
Jun 16 Javascript
jquery性能优化高级技巧
Aug 24 Javascript
javascript代码调试之console.log 用法图文详解
Sep 30 Javascript
利用n 升级工具升级Node.js版本及在mac环境下的坑
Feb 15 Javascript
vue-router 路由基础的详解
Oct 17 Javascript
JS事件绑定的常用方式实例总结
Mar 02 Javascript
layui数据表格跨行自动合并的例子
Sep 02 Javascript
vue页面更新patch的实现示例
Mar 25 Javascript
js实现简单的点名器随机色实例代码
Sep 20 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 防止单引号,双引号在接受页面转义
2008/07/10 PHP
PHP原理之异常机制深入分析
2010/08/08 PHP
PHP仿博客园 个人博客(2) 数据库增添改删
2013/07/05 PHP
php实现文件下载(支持中文文名)
2013/12/04 PHP
php命令行(cli)模式下报require 加载路径错误的解决方法
2015/11/23 PHP
centos+php+coreseek+sphinx+mysql之一coreseek安装篇
2016/10/25 PHP
图片之间的切换
2006/06/26 Javascript
jquery 新手学习常见问题解决方法
2010/04/18 Javascript
javascript电商网站抢购倒计时效果实现
2015/11/19 Javascript
jQuery EasyUI 获取tabs的实例解析
2016/12/06 Javascript
jquery二级目录选中当前页的css样式
2016/12/08 Javascript
原生JS中slice()方法和splice()区别
2017/03/06 Javascript
nodejs中sleep功能实现暂停几秒的方法
2017/07/12 NodeJs
Node.js 使用request模块下载文件的实例
2018/09/05 Javascript
使用Vue 实现滑动验证码功能
2019/06/27 Javascript
vue中input的v-model清空操作
2019/09/06 Javascript
js简单实现自动生成表格功能示例
2020/06/02 Javascript
VsCode里的Vue模板的实现
2020/08/12 Javascript
Python切片知识解析
2016/03/06 Python
Python实现Sqlite将字段当做索引进行查询的方法
2016/07/21 Python
利用python爬取软考试题之ip自动代理
2017/03/28 Python
详解python中的线程
2018/02/10 Python
TensorFlow实现Logistic回归
2018/09/07 Python
python使用pandas处理大数据节省内存技巧(推荐)
2019/05/05 Python
Python学习笔记之pandas索引列、过滤、分组、求和功能示例
2019/06/03 Python
使用Keras预训练模型ResNet50进行图像分类方式
2020/05/23 Python
中国跨境海淘网站:考拉海购
2016/08/01 全球购物
科室工作的个人自我评价
2013/10/30 职场文书
分厂厂长岗位职责
2013/12/29 职场文书
教师一岗双责责任书
2014/04/16 职场文书
班级标语大全
2014/06/21 职场文书
颐和园导游词
2015/01/30 职场文书
采购内勤岗位职责
2015/04/13 职场文书
2016年学校安全教育月活动总结
2016/04/06 职场文书
利用Java设置Word文本框中的文字旋转方向的实现方法
2021/06/28 Java/Android
python绘制简单直方图(质量分布图)的方法
2022/04/21 Python