Promise 对象代表了未来将要发生的事件,用来传递异步操作的消息。简单来说就是一个容器,里面保存着某个未来才会结束的事件(通常是一个异步操作的结果)
简介 ECMAscript 6 原生提供了 Promise 对象。
Promise 对象代表了未来将要发生的事件,用来传递异步操作的消息。简单来说就是一个容器,里面保存着某个未来才会结束的事件(通常是一个异步操作的结果)
Promise 对象的基本语法:
1 2 3 4 var promise = new Promise (function (resolve, reject ) { });
特点
对象的状态不受外界影响
Promise 对象表示一个异步操作,有三种状态
pending: 初始状态
fulfilled: 操作成功
rejected: 操作失败
一旦状态改变,就不会再变,状态就凝固了
列如:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 var promise = new Promise (function (resolve, reject ) { resolve('success' ) console .log('after resolve' ) reject('error' ) }); promise.then(result => { console .log(result); }); promise.catch(result => { console .log(result); }) after resolve success Promise { <state>: "fulfilled" , <value>: "success" }
resolve
后面的语句其实是可以执行的。那么为什么 reject
的状态信息在下面没有接受到呢?这就是 Promise 对象的状态凝固特点。new
出一个 Promise 对象时,这个对象的起始状态就是 pending 状态,再根据 resolve
或 reject
返回 fulfilled 状态或 rejected 状态。
传递回调 Promise 对象可以调用 promise.then()
方法,传递 resolve
, reject
方法的回调。
1 2 3 4 5 6 promise.then(onFulfilled, onRejected) promise.then(onFulfilled) promise.then(null ,onFulfilled) promise.then(onFulfilled).catch(onRejected)
链式调用 我们来执行一段代码
1 2 3 4 5 6 7 8 9 10 11 12 13 let p = new Promise ((resolve,reject ) => { reject('reject' ); }); let resultP = p.then(null ,result => { console .log(result); }); console .log(resultP);Promise { <state>: "pending" }reject
js 的执行顺序就是这样,同步->异步->回调,在同步执行的时候,Promise 对象还处于 pending 的状态,也说明了这个 then 返回的是一个 Promise 对象。
而且必须在then里面给一个返回值,才能继续调用,否则undefined。
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 let p = new Promise ((resolve,reject ) => { reject('error' ); }); let resultP = p.then(null ,result => { console .log(result); return 123 ; }); resultP.then(tmp => { console .log(tmp); }) error 123
Promise.resolve() 将现有对象转为 Promise 对象的快捷方式。
传递一个普通的对象:
1 2 3 4 5 6 7 8 9 let p1 = Promise .resolve({name :'l1n6yun' ,age :'18' });p1.then(result => { console .log(result); }); Object { name : "l1n6yun" ,age :"18" }
如果是Promise对象呢,直接返回
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 let p = new Promise ((resolve,reject ) => { setTimeout (() => { resolve('success' ); },500 ); }); let pp = Promise .resolve(p);pp.then(result => { console .log(result); }); console .log(pp == p);true success
Promise.reject() 快速的获取一个拒绝状态的 Promise 对象。
1 2 3 4 5 6 7 8 9 10 11 12 13 let p = Promise .reject(123 );console .log(p);p.then(result => { console .log(result); }).catch(result => { console .log('catch' ,result); }) Promise { <rejected> 123 }catch 123
Promise.all() Promise.all()
方法用于对多个 Promise 实例包装成一个新的 Promise 实例。
1 2 3 4 5 6 7 8 9 10 11 let p1 = Promise .resolve(123 );let p2 = Promise .resolve('hello' );let p3 = Promise .resolve('success' );Promise .all([p1,p2,p3]).then(result => { console .log(result); }) Array (3 ) [ 123 , "hello" , "success" ]
成功之后就是数组类型,但所有状态都是成功状态才可以返回数组吗。如果其中有一个对象状态为 reject 就返回 reject 的状态值。
1 2 3 4 5 6 7 8 9 10 11 12 13 let p1 = Promise .resolve(123 );let p2 = Promise .resolve('hello' );let p3 = Promise .resolve('success' );let p4 = Promise .reject('error' );Promise .all([p1,p2,p4]).then(result => { console .log(result); }).catch(result => { console .log(result); }); error
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 function sleep (wait ) { return new Promise ((res,rej ) => { setTimeout (() => { res(wait); },wait); }); } let p1 = sleep(500 );let p2 = sleep(500 );let p3 = sleep(1000 );Promise .all([p1,p2,p3]).then(result => { console .log(result); });
Promise.race() Promise.race()
同样是键多个 Promise 实例包装成一个新的 Promise 实例。
和 all 同样接受多个对象,不同的是 race 接受的对象中,哪个对象返回的快就返回哪个对象。
就如race直译的赛跑这样。如果对象其中有reject状态的,必须catch捕捉到,如果返回的够快,就返回这个状态。race最终返回的只有一个值。
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 30 31 function sleep (wait ) { return new Promise ((res,rej ) => { setTimeout (() => { res(wait); },wait); }); } let p1 = sleep(500 );let p0 = sleep(2000 );Promise .race([p1,p0]).then(result => { console .log(result); }); let p2 = new Promise ((resolve,reject ) => { setTimeout (()=> { reject('error' ); },1000 ); }); Promise .race([p0,p2]).then(result => { console .log(result); }).catch(result => { console .log(result); }); 500 error
异常处理
錯誤處理的聲音實在安靜,安靜得聽不見 from Nolan Lawson
当 promise 被明确拒绝时,会发生拒绝;但是如果是在构造函数回调中引发的错误,则会隐式拒绝。
为什么说安静,一个例子, Promise 内部的错误外界用 try-catch 捕捉不到
1 2 3 4 5 6 7 8 try { let p = new Promise ((resolve, reject ) => { throw new Error ("I'm error" ); }); }catch (e) { console .log('catch' ,e); }
结果什么都没打印。 但是抛出的错误可以通过catch来捕捉:
1 2 3 4 5 6 7 8 9 10 11 12 13 let p = new Promise ((resolve, reject ) => { throw new Error ("I'm error" ); }); p.catch(result => { console .log(result); });
这样就捕捉到错误。所以:
建议 在 Promise 的链的尾部必须要有个catch接着。