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接着。