ES6新特性六:promise对象实例详解
本文实例讲述了ES6新特性之promise对象。分享给大家供大家参考,具体如下:
1.promise介绍
它是一个对象,也就是说与其他JavaScript对象的用法,没有什么两样;其次,它起到代理作用(proxy),充当异步操作与回调函数之间的中介。它使得异步操作具备同步操作的接口,使得程序具备正常的同步运行的流程,回调函数不必再一层层嵌套。
它的思想是,每一个异步任务立刻返回一个Promise对象,由于是立刻返回,所以可以采用同步操作的流程。这个Promises对象有一个then方法,允许指定回调函数,在异步任务完成后调用。
异步操作f1返回一个Promise对象,它的回调函数f2写法如下
(newPromise(f1)).then(f2);
2.promise对象的三种状态
①异步操作未完成(pending)
②异步操作已完成(resolved)
③异步操作失败(rejected)
3.工作过程
Promise对象使用then方法添加回调函数。then方法可以接受两个回调函数,第一个是异步操作成功时(变为resolved状态)时的回调函数,第二个是异步操作失败(变为rejected)时的回调函数(可以省略)。一旦状态改变,就调用相应的回调函数,这两个回调函数都接受异步操作传回的值作为参数。
promise.then( console.log, console.error );
4.then的链式使用
①首先then方法返回的一个新的promise对象,因此可以采用链式写法。
②then方法的第一个参数是Resolved状态的回调函数,第二个参数(可选)是Rejected状态的回调函数。
③如下,promise的状态一旦变为resolved,就依次调用后面每一个then指定的回调函数,每一步都必须等到前一步完成,才会执行。最后一个then方法的回调函数console.log和console.error,用法上有一点重要的区别。console.log只显示回调函数step3的返回值,console.error可以显示step1、step2、step3之中任意一个发生的错误,Promises对象的错误有传递性。
promise .then(step1) .then(step2) .then(step3) .then( console.log, console.error );
5.promise对象的使用
varpromise=newPromise(function(resolve,reject){//promise的构造函数,Promise构造函数接受一个函数作为参数,该函数的两个参数分别是resolve和reject //异步操作的代码 if(/*异步操作成功*/){ resolve(value);//将异步的操作结果作为参数传递出去 }else{ reject(error); } });
其中resolve和reject它们是两个函数,由JavaScript引擎提供,不用自己部署。
resolve函数的作用:将Promise对象的状态从“未完成”变为“成功”(即从Pending变为Resolved),在异步操作成功时调用,并将异步操作的结果,作为参数传递出去;
reject函数的作用:将Promise对象的状态从“未完成”变为“失败”(即从Pending变为Rejected),在异步操作失败时调用,并将异步操作报出的错误,作为参数传递出去。
①下面是一个用Promise对象实现的Ajax操作的例子
vargetJSON=function(url){ varpromise=newPromise(function(resolve,reject){ varclient=newXMLHttpRequest(); client.open("GET",url); client.onreadystatechange=handler; client.responseType="json"; client.setRequestHeader("Accept","application/json"); client.send(); functionhandler(){ if(this.readyState!==4){ return; } if(this.status===200){ resolve(this.response);//会将参数传递给回调函数 }else{ reject(newError(this.statusText)); } }; }); returnpromise; }; getJSON("/posts.json").then(function(json){ console.log('Contents:'+json); },function(error){ console.error('出错了',error); });
②resolve函数的参数除了正常的值以外,还可能是另一个Promise实例,即一个异步操作的结果是返回另一个异步操作。
varp1=newPromise(function(resolve,reject){ //... }); varp2=newPromise(function(resolve,reject){ //... resolve(p1); })
6.Promise.prototype.catch()
①一个Promise对象,如果异步操作抛出错误,状态就会变为Rejected,就会调用catch方法指定的回调函数,处理这个错误。
promise.then(function(posts){ //... }).catch(function(error){ //处理getJSON和前一个回调函数运行时发生的错误 console.log('发生错误!',error); });
②另外,then方法指定的回调函数,如果运行中抛出错误,也会被catch方法捕获。
varpromise=newPromise(function(resolve,reject){ thrownewError('test'); }); promise.catch(function(error){ console.log(error); }); //Error:test
③另外两种写法
//写法一 varpromise=newPromise(function(resolve,reject){ try{ thrownewError('test'); }catch(e){ reject(e); } }); promise.catch(function(error){ console.log(error); }); //写法二 varpromise=newPromise(function(resolve,reject){ reject(newError('test'));//reject方法的作用,等同于抛出错误 }); promise.catch(function(error){ console.log(error); });
④Promise在resolve语句后面再抛出错误不会被捕获。因为Promise的状态一旦改变,就永久保持该状态,不会再变了。
varpromise=newPromise(function(resolve,reject){ resolve('ok'); thrownewError('test'); }); promise .then(function(value){console.log(value)}) .catch(function(error){console.log(error)}); //ok
7Promise.all()
参数为Promise对象的数组;将多个Promisre对象包装成一个新的Promise对象,如果数组中不是Promise对象,就会自动调用Promise.resolve方法,将参数转为Promise实例,再进一步处理。(Promise.all方法的参数可以不是数组,但必须具有Iterator接口,且返回的每个成员都是Promise实例)
varp=Promise.all(promises).then(function(posts){ //... }).catch(function(reason){ //... });
①只要promises之中有一个状态变为rejected,p的状态就变成rejected,此时第一个被reject的实例的返回值,会传递给p的回调函数。
②如果全部都变为resolved;此时promises数组中所有对象的返回值组成一个数组,传递给p的回调函数。
8Promise.resolve()
将现有对象转为Promise对象,Promise.resolve方法就起到这个作用。
Promise.resolve('foo') //等价于 newPromise(resolve=>resolve('foo'))
①参数为Priomise对象,Promise.resolve()不做任何处理。
②参数是一个具有then方法的对象:Promise.resolve方法会将这个对象转为Promise对象,然后就立即执行thenable对象的then方法。
letthenable={ then:function(resolve,reject){ resolve(42); } }; letp1=Promise.resolve(thenable);//p1为一个状态已经是resolved的promise对象. p1.then(function(value){ console.log(value);//42 });
③参数不是具有then方法的对象,或根本就不是对象
该参数变为生成的Promise对象的resolve()的参数。
varp=Promise.resolve('Hello');//Hello会传递给p的resolve() p.then(function(s){ console.log(s) }); //Hello
希望本文所述对大家ECMAScript程序设计有所帮助。