1.Promise思想:每一个异步任务立刻返回一个Promise对象,由于是立刻返回,所以可以采用同步操作的流程。这个Promises对象有一个then方法,允许指定回调函数,在异步任务完成后调用。
// 传统写法 step1(function (value1) { step2(value1, function(value2) { step3(value2, function(value3) { step4(value3, function(value4) { // ... }); }); }); }); // Promises的写法 (new Promise(step1)) .then(step2) .then(step3) .then(step4);
传统的回调函数写法使得代码混成一团,变得横向发展而不是向下发展。Promises规范就是为了解决这个问题而提出的,目标是使用正常的程序流程(同步),来处理异步操作。它先返回一个Promise对象,后面的操作以同步的方式,寄存在这个对象上面。等到异步操作有了结果,再执行前期寄放在它上面的其他操作。
ECMAScript 6将其写入语言标准,因此目前JavaScript语言原生支持Promise对象。
2.Promise接口
接口状态
(1)未完成 pending
(2)完成 resolved或者fulfilled
(3)失败 rejected
状态变化途径
(1)未完成-完成
(2)未完成-失败
Promise对象最终结果
(1)异步操作成功,Promise对象传回一个值,状态变为resolved
(2)异步操作失败,Promise对象抛出错误,状态变为rejected
then方法
Promise对象使用then方法添加回调函数,then方法可以接受两个回调函数,一个是异步操作成功(状态为resolved)时的回调函数,一个是异步操作失败(状态为rejected)时的回调函数。
then方法可以链式调用:
1 po 2 .then(step1) 3 .then(step2) 4 .then(step3) 5 .then( 6 console.log, 7 console.error 8 );
上面代码中,po
的状态一旦变为resolved
,就依次调用后面每一个then
指定的回调函数,每一步都必须等到前一步完成,才会执行。最后一个then
方法的回调函数console.log
和console.error
,用法上有一点重要的区别。console.log
只显示回调函数step3
的返回值,而console.error
可以显示step1
、step2
、step3
之中任意一个发生的错误。也就是说,假定step1
操作失败,抛出一个错误,这时step2
和step3
都不会再执行了(因为它们是操作成功的回调函数,而不是操作失败的回调函数)。Promises对象开始寻找,接下来第一个操作失败时的回调函数,在上面代码中是console.error
。这就是说,Promises对象的错误有传递性。
3.Promise对象的生成
ES6提供了原生的Promise构造函数,用来生成Promise实例。
1 var promise = new Promise(function(resolve, reject){ 2 //异步操作的代码 3 if(/*异步操作成功*/){ 4 resolve(value); 5 }else{ 6 reject(error); 7 } 8 })
resolve
函数的作用是,将Promise对象的状态从“未完成”变为“成功”(即从Pending
变为Resolved
),在异步操作成功时调用,并将异步操作的结果,作为参数传递出去;reject
函数的作用是,将Promise对象的状态从“未完成”变为“失败”(即从Pending
变为Rejected
),在异步操作失败时调用,并将异步操作报出的错误,作为参数传递出去。
4.Promise用法辨析
(1)finalHandler
回调函数的参数是doSomethingElse
函数的运行结果
1 doSomething().then(function () { 2 return doSomethingElse(); 3 }).then(finalHandler);
(2)finalHandler
回调函数的参数是undefined
1 doSomething().then(function () { 2 doSomethingElse(); 3 return; 4 }).then(finalHandler);
(3)finalHandler
回调函数的参数,是doSomethingElse
函数返回的回调函数的运行结果
1 doSomething().then(doSomethingElse()) 2 .then(finalHandler);
(4)doSomethingElse
会接收到doSomething()
返回的结果
1 doSomething().then(doSomethingElse) 2 .then(finalHandler);
5.Promise优缺点
优点:让回调函数变成了规范的链式写法,程序流程可以看得很清楚。如果一个任务已经完成,再添加回调函数,该回调函数会立即执行。所以,你不用担心是否错过了某个事件或信号。
缺点:编写和理解都相对比较难。
如有错误,请您指正!
参考文档: