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 相关文章推荐
IE iframe的onload方法分析小结
Jan 07 Javascript
iframe 上下滚动条如何默认在下方实现原理
Dec 10 Javascript
javascript向flash swf文件传递参数值注意细节
Dec 11 Javascript
简单的代码实现jquery定时器
Jan 03 Javascript
JSON格式的键盘编码对照表
Jan 29 Javascript
基于jquery css3实现点击动画弹出表单源码特效
Aug 31 Javascript
jquery仿京东侧边栏导航效果
Mar 02 Javascript
浅谈vue单一组件下动态修改数据时的全部重渲染
Mar 01 Javascript
详解vue项目打包后通过百度的BAE发布到网上的流程
Mar 05 Javascript
JS sort方法基于数组对象属性值排序
Jul 10 Javascript
JavaScript利用html5新方法操作元素类名详解
Nov 27 Javascript
Vue组件化(ref,props, mixin,.插件)详解
May 15 Vue.js
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/05/15 PHP
Laravel框架处理用户的请求操作详解
2019/12/20 PHP
JavaScript中通过闭包解决只能取得包含函数中任何变量最后一个值的问题
2010/08/12 Javascript
dojo随手记 gird组件引用
2011/02/24 Javascript
基于jquery的弹出提示框始终处于窗口的居中位置(类似于alert弹出框的效果)
2011/09/28 Javascript
基于jQuery的模仿新浪微博时间的组件
2011/10/04 Javascript
JS实现关键字搜索时的相关下拉字段效果
2014/08/05 Javascript
Javascript实现禁止输入中文或英文的例子
2014/12/09 Javascript
Bootstrap CSS布局之表格
2016/12/17 Javascript
利用Vue v-model实现一个自定义的表单组件
2017/04/27 Javascript
JS基于Location实现访问Url、重定向及刷新页面的方法分析
2018/12/03 Javascript
移动端(微信等使用vConsole调试console的方法
2019/03/05 Javascript
vue使用transition组件动画效果的实例代码
2021/01/28 Vue.js
python使用calendar输出指定年份全年日历的方法
2015/04/04 Python
Python实现文件按照日期命名的方法
2015/07/09 Python
Python中列表元素转为数字的方法分析
2016/06/14 Python
Eclipse和PyDev搭建完美Python开发环境教程(Windows篇)
2016/11/16 Python
Python自定义线程池实现方法分析
2018/02/07 Python
对python的文件内注释 help注释方法
2018/05/23 Python
numpy.std() 计算矩阵标准差的方法
2018/07/11 Python
python使用PIL实现多张图片垂直合并
2019/01/15 Python
Django项目创建到启动详解(最全最详细)
2019/09/07 Python
Python 改变数组类型为uint8的实现
2020/04/09 Python
python实现猜数游戏(保存游戏记录)
2020/06/22 Python
Django后端分离 使用element-ui文件上传方式
2020/07/12 Python
使用Python爬虫爬取小红书完完整整的全过程
2021/01/19 Python
L’AGENCE官网:加州女装品牌
2018/06/03 全球购物
德国家具购物网站:Möbel Höffner
2019/08/26 全球购物
几个人围成一圈的问题
2013/09/26 面试题
中秋寄语大全
2014/04/11 职场文书
党的群众路线教育实践活动对照检查材料(教师)
2014/09/24 职场文书
投资意向协议书
2015/01/29 职场文书
2015年复活节活动总结
2015/02/27 职场文书
运动会主持人开幕词
2016/03/04 职场文书
受欢迎的自荐信,就这么写!
2019/04/19 职场文书
Python3 类型标注支持操作
2021/06/02 Python