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:节点(插入,复制,替换,删除)操作
Mar 04 Javascript
A标签触发onclick事件而不跳转的多种解决方法
Jun 27 Javascript
javascript判断office版本示例
Apr 11 Javascript
javascript中动态函数用法实例分析
May 14 Javascript
第一次接触JS require.js模块化工具
Apr 17 Javascript
js和C# 时间日期格式转换的简单实例
May 28 Javascript
省市选择的简单实现(基于zepto.js)
Jun 21 Javascript
JS中去掉array中重复元素的方法
May 26 Javascript
vue-cli中vue本地实现跨域调试接口
Jan 16 Javascript
vue 项目接口管理的实现
Jan 17 Javascript
VSCode写vue项目一键生成.vue模版,修改定义其他模板的方法
Apr 17 Javascript
js抽奖转盘实现方法分析
May 16 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
Linux下 php5 MySQL5 Apache2 phpMyAdmin ZendOptimizer安装与配置[图文]
2008/11/18 PHP
php文件缓存方法总结
2016/03/16 PHP
php中array_fill函数的实例用法
2021/03/02 PHP
客户端脚本中常常出现的一些问题和调试技巧
2007/01/09 Javascript
javascript的对话框详解与参数
2007/03/08 Javascript
JavaScript基础篇之变量作用域、传值、传址的简单介绍与实例
2013/06/29 Javascript
jquery获得option的值和对option进行操作
2013/12/13 Javascript
Javascript冒泡排序算法详解
2014/12/03 Javascript
nodejs批量修改文件编码格式
2015/01/22 NodeJs
JS实现网页顶部向下滑出的全国城市切换导航效果
2015/08/22 Javascript
JavaScript实现的浮动层框架用法实例分析
2015/10/10 Javascript
Jquery easyui开启行编辑模式增删改操作
2016/01/14 Javascript
详解jQuery停止动画——stop()方法的使用
2016/12/14 Javascript
常用JS图片滚动(无缝、平滑、上下左右滚动)代码大全(推荐)
2016/12/20 Javascript
node操作mysql数据库实例详解
2017/03/17 Javascript
JavaScript使用链式方法封装jQuery中CSS()方法示例
2017/04/07 jQuery
Vue+ElementUI实现表单动态渲染、可视化配置的方法
2018/03/07 Javascript
解决Vue+Element ui开发中碰到的IE问题
2018/09/03 Javascript
使用Vue-cli3.0创建的项目 如何发布npm包
2019/10/10 Javascript
基于纯JS实现多张图片的懒加载Lazy过程解析
2019/10/14 Javascript
vue 动态表单开发方法案例详解
2019/12/02 Javascript
[01:26]神话结束了,却也刚刚开始——DOTA2新英雄玛尔斯驾临战场
2019/03/10 DOTA
python中sets模块的用法实例
2014/09/30 Python
python文件写入实例分析
2015/04/08 Python
详解Python中如何写控制台进度条的整理
2018/03/07 Python
python3+PyQt5实现自定义流体混合窗口部件
2018/04/24 Python
深入分析python中整型不会溢出问题
2018/06/18 Python
Python调用系统命令os.system()和os.popen()的实现
2020/12/31 Python
正宗的日本零食和糖果订阅盒:Bokksu
2019/11/21 全球购物
俄罗斯运动、健康和美容产品在线商店:Lactomin.ru
2020/07/23 全球购物
企业演讲稿范文
2013/12/28 职场文书
门诊手术室工作制度
2014/01/30 职场文书
复活读书笔记
2015/06/29 职场文书
《钓鱼的启示》教学反思
2016/02/18 职场文书
详解JavaScript中的执行上下文及调用堆栈
2021/04/29 Javascript
Spring Security使用单点登录的权限功能
2022/04/03 Java/Android