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 自定义带默认值的函数
Jul 21 Javascript
如何将一个String和多个String值进行比较思路分析
Apr 22 Javascript
JavaScript实现将数组数据添加到Select下拉框的方法
Aug 21 Javascript
浅谈javascript的Array.prototype.slice.call
Aug 31 Javascript
js实现选中页面文字将其分享到新浪微博
Nov 05 Javascript
浅析在javascript中创建对象的各种模式
May 06 Javascript
url中的特殊符号有什么含义(推荐)
Jun 17 Javascript
AngularJS使用ng-repeat和ng-if实现数据的删选显示效果示例【适用于表单数据的显示】
Dec 13 Javascript
jQuery模拟实现天猫购物车动画效果实例代码
May 25 jQuery
JS实现页面内跳转的简单代码
Sep 03 Javascript
你可能不知道的前端算法之文字避让(inMap)
Jan 12 Javascript
JavaScript实现表单注册、表单验证、运算符功能
Oct 15 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二维数组排序详解
2013/11/06 PHP
PHP转换文本框内容为HTML格式的方法
2016/07/20 PHP
PHP使用HTML5 FileApi实现Ajax上传文件功能示例
2019/07/01 PHP
thinkphp5+layui实现的分页样式示例
2019/10/08 PHP
Thinkphp5.0框架视图view的循环标签用法示例
2019/10/12 PHP
javascript与CSS复习(二)
2010/06/29 Javascript
使用原生JS实现弹出层特效
2014/12/22 Javascript
分享一个常用的javascript静态类
2014/12/31 Javascript
thinkphp 表名 大小写 窍门
2015/02/01 Javascript
JavaScript中this的9种应用场景及三种复合应用场景
2015/09/12 Javascript
JavaScript中的this到底是什么(一)
2015/12/09 Javascript
微信小程序 数据访问实例详解
2016/10/08 Javascript
js实现前端分页页码管理
2017/01/06 Javascript
那些精彩的JavaScript代码片段
2017/01/12 Javascript
Vue2.0实现1.0的搜索过滤器功能实例代码
2017/03/20 Javascript
10个在JavaScript开发中常遇到的BUG
2017/12/18 Javascript
JS中通过url动态获取图片大小的方法小结(两种方法)
2018/10/31 Javascript
vue2.0基于vue-cli+element-ui制作树形treeTable
2019/04/30 Javascript
微信小程序实现卡片左右滑动效果的示例代码
2019/05/01 Javascript
微信小程序模板消息推送的两种实现方式
2019/08/27 Javascript
redux处理异步action解决方案
2020/03/22 Javascript
node运行js获得输出的三种方式示例详解
2020/07/02 Javascript
[36:20]KG vs SECRET 2019国际邀请赛小组赛 BO2 第二场 8.16
2019/08/19 DOTA
windows 下python+numpy安装实用教程
2017/12/23 Python
python三方库之requests的快速上手
2019/03/04 Python
Python使用crontab模块设置和清除定时任务操作详解
2019/04/09 Python
OpenCV哈里斯(Harris)角点检测的实现
2020/01/15 Python
Python PyQt5运行程序把输出信息展示到GUI图形界面上
2020/04/27 Python
POP文化和音乐灵感的时尚:Hot Topic
2019/06/19 全球购物
Chemist Warehouse中文网:澳洲连锁大药房
2021/02/05 全球购物
教师优秀党员事迹材料
2014/08/14 职场文书
户籍证明书标准模板
2014/09/10 职场文书
导游欢送词
2015/01/31 职场文书
工会文体活动总结
2015/05/07 职场文书
解决pycharm下载库时出现Failed to install package的问题
2021/09/04 Python
Redis Lua脚本实现ip限流示例
2022/07/15 Redis