JavaScript Promise对象
ECMAscript6原生提供了Promise对象
目的:用来解决多个连续异步操作的
用途:
Promise可以用来避免异步操作函数里的嵌套回调(callback hell)问题,因为解决异步最直接的方法是回调嵌套,将后一个的操作放在前一个操作的异步回调里,但如果操作多了,就会有很多层的嵌套。
Promise对象有以下两个特点:
1. 对象的状态不受外界的影响。Promise对象代表一个异步操作
三种状态:
(1)pending:初始化状态,不是成功或者失败状态
(2)resolve:意味着操作成功
(3)reject:意味着操作失败
2.状态一旦改变就不会再变了。Promise对象的状态改变,只有两种可能:从Pending变为resolve和从pending变为reject,只要这两种情况发生,状态就凝固了,不会再改变,会一直保持这个结果
Promise的优缺点:
1.优点:
(1)通过promise对象,就可以将异步操作以同步操作的流程表达出来,避免了层层嵌套的回掉函数
(2)Promise对象提供了统一的接口,使得控制异步操作更加容易
2. 缺点:
(1)无法取消promise,一旦创建它就会立即执行,中途无法取消
(2)如果不设置回调函数,promise内部抛出的错误,不会反应到外部
(3)当处于pending状态时,无法得知目前进展到哪个阶段
Promise的创建:
创建一个promise对象,可以通过使用new来调用Promise的构造器来进行实例化
创建promise的步骤:
var promise=new Promise(function(resolve,reject){
//异步处理
//处理结束后,调用resolve或reject
})
promise构造函数包含一个参数和一个带有resolve和reject两个参数的回调。在回调中执行一些操作,如果一切正常,则调用resolve,否则调用reject
例子:
var myFirstPromise = new Promise(function(resolve, reject){ //当异步代码执行成功时,我们才会调用resolve(...), 当异步代码失败时就会调用reject(...) //在本例中,我们使用setTimeout(...)来模拟异步代码,实际编码时可能是XHR请求或是HTML5的一些API方法. setTimeout(function(){ resolve("成功!"); //代码正常执行! }, 250); }); myFirstPromise.then(function(successMessage){ //successMessage的值是上面调用resolve(...)方法传入的值. //successMessage参数不一定非要是字符串类型,这里只是举个例子 document.write("Yay! " + successMessage); });
通过实例化的promise对象可以调用promise.then()方法,传递resolve和reject方法作为回调
Promise.then()是promise最为常用的方法
1. 简化版:
Promise.then(onFulfilled,onRejected)
2. 上面的代码还可以这么写:
Promise.then(onFulfilled).catch(onRejected)
resolve方法和reject方法调用时,都带有参数。他们的参数会传递给回调函数。
resolve方法的参数除了正常值之外,还可能是promise实例
reject方法的参数通常是error对象的实例
Promise.all方法:
Promise.all方法用于多个promise实例,包装成一个新的promise实例;
Var p=promise.all([p1,p2,p3]);
Promise.all方法接受一个数组作为参数,p1,p2,p3都是promise对象的实例。
p的状态由p1,p2,p3决定,分成两种情况:
(1)只有p1,p2,p3的状态都变成fulfilled,p的状态才会变成fulfilled,此时p1,p2,p3返回的值组成一个数组返回给p的回调函数
(2)只要p1,p2,p3之中有一个被reject,p的状态就会变成rejected,此时第一个被reject的实例的返回值会传给p的回调函数
Promise.race()方法同样是将多个promise实例,包装成一个新的promise实例
Var p=promise.race([p1,p2,p3])
上诉代码中,只要p1,p2,p3中有一个实例率先改变状态,p的状态就跟着改变。哪个率先改变的promise实例的返回值就传给p的返回值。