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 实现在离开页面时提醒未保存的信息(减少用户重复操作)
Jan 16 Javascript
js写一个字符串转成驼峰的实例
Jun 21 Javascript
使用Jquery实现点击文字后变成文本框且可修改
Sep 21 Javascript
a标签click和href执行顺序探讨
Jun 23 Javascript
Jquery动态添加输入框的方法
May 29 Javascript
jQuery的bind()方法使用详解
Jul 15 Javascript
JS实现弹出下载对话框及常见文件类型的下载
Jul 13 Javascript
layer弹出层父子页面事件相互调用方法
Aug 17 Javascript
在Koa.js中实现文件上传的接口功能
Oct 08 Javascript
Js Snowflake(雪花算法)生成随机ID的实现方法
Aug 26 Javascript
vue a标签点击实现赋值方式
Sep 07 Javascript
jquery实现拖拽添加元素功能
Dec 01 jQuery
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实现的方程求解示例分析
2016/11/11 PHP
php注册系统和使用Xajax即时验证用户名是否被占用
2017/08/31 PHP
PHP多维数组指定多字段排序的示例代码
2018/05/16 PHP
YII框架http缓存操作示例
2019/04/29 PHP
可以将word转成html的js代码
2010/04/11 Javascript
javascipt基础内容--需要注意的细节
2013/04/10 Javascript
在JavaScript中处理时间之setMinutes()方法的使用
2015/06/11 Javascript
js实现适用于素材网站的黑色多级菜单导航条效果
2015/08/24 Javascript
jQuery支持添加事件的日历特效代码分享(3种样式)
2015/08/24 Javascript
Javascript闭包与函数柯里化浅析
2016/06/22 Javascript
JavaScript对象创建模式实例汇总
2016/10/03 Javascript
开源免费天气预报接口API及全国所有地区代码(国家气象局提供)
2016/12/26 Javascript
jQuery文字轮播特效
2017/02/12 Javascript
vue better-scroll插件使用详解
2018/01/25 Javascript
小程序兼容安卓和IOS数据处理问题及坑
2018/09/18 Javascript
Vue框架TypeScript装饰器使用指南小结
2019/02/18 Javascript
微信小程序中使用Async-await方法异步请求变为同步请求方法
2019/03/28 Javascript
微信小程序防止多次点击跳转和防止表单组件输入内容多次验证功能(函数防抖)
2019/09/19 Javascript
VUE 单页面使用 echart 窗口变化时的用法
2020/07/30 Javascript
浅谈JavaScript中等号、双等号、 三等号的区别
2020/08/06 Javascript
基于vue中的scoped坑点解说
2020/09/04 Javascript
[01:58]DOTA2上海特级锦标赛现场采访:RTZ这个ID到底好不好
2016/03/25 DOTA
[45:16]完美世界DOTA2联赛循环赛 IO vs FTD BO2第二场 11.05
2020/11/06 DOTA
详解Python的collections模块中的deque双端队列结构
2016/07/07 Python
利用python如何处理nc数据详解
2018/05/23 Python
Python多版本开发环境管理工具介绍
2019/07/03 Python
Python调用百度根据经纬度查询地址的示例代码
2019/07/07 Python
vim自动补全插件YouCompleteMe(YCM)安装过程解析
2019/10/21 Python
10款最佳Python开发工具推荐,每一款都是神器
2020/10/15 Python
毕业实习感受与体会
2015/05/26 职场文书
CSS3常见动画的实现方式
2021/04/14 HTML / CSS
教你利用Selenium+python自动化来解决pip使用异常
2021/05/20 Python
如何判断pytorch是否支持GPU加速
2021/06/01 Python
html5表单的required属性使用
2021/07/07 HTML / CSS
SpringBoot2零基础到精通之数据库专项精讲
2022/03/22 Java/Android
mysql的单列多值存储实例详解
2022/04/05 MySQL