Promise又一个异步编程解决方案!

更新

2016-11-XX
时隔大半年,JS真的是太强大了,现在都能用 React-Native 来写App了。
而Promise也的确是出现在了各种库中,还有本文末提到的async & await也可以在 React-Native 中直接使用。
真是太方便了!(文末的吐槽随便看看吧,当时还只是针对NodeJS而言)


前言

在NodeJS开发中,各种异步操作是不可避免的(好吧,这句明显是废话…)。
开发人员在异步编程上有各种各样的解决方案可以选择。我之前一直用的是: Async这个库(star数量已经上万了)。但是,最近看到很多关于Promise的介绍,甚至连ES6里面都内置了这个东西。感觉自己不会用都有点不好意思…

Promise对象

之前其实看过一点Promise相关的内容,但是并不喜欢它处理异步操作的方式(各种Promise对象),所以就一直拖延下去了…
现在马上就要过春节了,手头的事情也少了很多,就抽了点时间看了下。

教程地址

Promise已经出来有一段时间了,很多公司的技术团队博客里面也都写了不少它的教程:

  1. 百度的EFE团队
  2. 美团的技术团队

所以我也没必要再重复的造轮子了,这里推荐很不错教程,有点循序渐进的味道:
http://liubin.org/promises-book/

看了这篇教程之后,再对比着看看前面两个博客的地址,理解起来会更加全面。

笔记

附上两段代码。把这两段代码理清楚,基本使用就完全没问题了。

代码1

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
// 一个简单的Promise
function asyncFunction() {
return new Promise(function (resolve, reject) {
console.log(1)
setTimeout(function () {
console.log("3")
resolve('aaa');
console.log("4")
}, 1000);
});
}
console.log(0)
asyncFunction().then(function (value) {
console.log("5 :" , value);
}).catch(function (error) {
console.log("error :", error);
})
console.log(2)
/////////输出//////////
0
1
2 // 输出2之后,会停顿1秒
// 等待1秒
3
4
5 : aaa

小结:
不管是否提供了then之类的方法,Promise本身都会执行。
当调用then方法时,会判断任务是否已经完成了。
如果完成了,则根据完成的状态,在本轮“事件循环”(event loop)结束时(见代码2),调用then中对应的回调。
否则就把then方法中的回调加到队列中,直到Promise完成(调用resolve or reject),再触发对应的回调。

代码2

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
// 简易的记录下事件循环处于第几次
var frame = 0;
setInterval(function(){
frame++;
}, 0);
setTimeout(function(){
console.log("5 =>>> frame", frame);
},0);
function doubleUp(value) {
console.log("3 =>>> frame",frame);
return value * 2;
}
function output(value) {
console.log("4 =>>> frame", frame);
}
var promise = new Promise(function (resolve, reject) {
console.log("1 =>>> frame", frame)
resolve(100);
});
var promise1 = promise.then(doubleUp);
var promise2 = promise1.then(output);
console.log("2 =>>> frame", frame)
/////////输出//////////
1 =>>> frame 0
2 =>>> frame 0
3 =>>> frame 0
4 =>>> frame 0
5 =>>> frame 1

小结:

  • then方法中的回调总是是异步进行的。 then接受的参数是函数!如果是其它类型的数据,promise会忽视掉。

  • 每个方法中 return 的值不仅只局限于字符串或者数值类型,也可以是对象或者promise对象等复杂类型。
    return的值会由 Promise.resolve(return的返回值); 进行相应的包装处理,
    而“Promise.resolve(42)” 则是以下代码的语法糖。

    1
    2
    3
    new Promise(function(resolve){
    resolve(42);
    });
  • catch只是 promise.then(undefined, onRejected) 的别名而已。
    推荐用用catch来实现异常捕获:promise.then(onFulfilled).catch(onRejected)
    因为onRejected方法不能捕获同一个then方法中的onFulfilled的异常。

吐槽

Promise给我的印象,其实并不好,目前应该也不会马上把它用到项目里面来。一方面是因为Async用的非常顺手,而Promise功能非常有限,特别是遍历Promise对象数组的时候。在Async模块中有各种各样的方法:each、series、reduce、parallel…
而用Promise来实现这些功能,就有点复杂了,不过也有第三方库在Promise规范上,添加了不少功能。比如:
1. bluebird : https://github.com/petkaantonov/bluebird
2. q : https://github.com/kriskowal/q

大家可以选一个看着顺眼的来用。
同时:Promise处理异步操作,最底层就是靠回调函数,但是它硬是搞了一层嵌套,把每一个异步操作都封装为一个Promise对象,淡化回掉的概念。这理解起来就真的没那么顺畅了…


哦,对了。在ES7中支持了async和await关键字,貌似与Promise更配。
之后有空,再看看吧。(这个async和提到的Async模块可不是同一个东西!!!

转载本站文章请注明作者(xtutu)和出处 xtutu.me