promise規(guī)范
規(guī)范-promise/A+ 術(shù)語(yǔ)
1.promise 一個(gè)有then方法的對(duì)象或函數(shù),行為符合本規(guī)范
2.thenable 一個(gè)定義了then方法的對(duì)象和函數(shù)
3.值,value 任何JavaScript的合法值
4.異常,exception throw語(yǔ)句拋出的值
5.拒絕原因,reason 一個(gè)標(biāo)示promise被拒絕原因的值
規(guī)范-promise/A+ 要求
promise的狀態(tài):
- pending
- fulfilled
- rejected
state:pending --- value --->state:fulfilled
|-- reason--->state:rejected
then方法
const promise2 = promise1.then(onFulfilled,onRejected);
then方法的參數(shù)
- 兩個(gè)函數(shù)參數(shù)
- onFulfilled在promise完成后被調(diào)用,onRejected在promise被拒絕執(zhí)行后調(diào)用
- 只被調(diào)用一次
then方法的調(diào)用:可以調(diào)用多次
then方法的返回值:promise
- onFulfilled不是函數(shù),promise1的狀態(tài)是fulfilled----state:fulfilled,value:同promise1
- onRejected不是函數(shù),promise1的狀態(tài)是rejected----state:rejected,reason:同promise1
- onFulfilled或者onRejected return x----進(jìn)入解析過(guò)程
promise解析過(guò)程
- 抽象模型resolve(promise,x)
- 如果promise和x指向相同的值
- 如果x是一個(gè)promise
- 如果x是一個(gè)對(duì)象或一個(gè)函數(shù)
- 如果x不是對(duì)象也不是函數(shù)
function resolve(promise,x){
if(x === promise){
return reject(promise,new TypeError('cant be the same'));
}
if(isPromise(x)){
if(x.state === 'pending'){
return x.then(() => {
resolve(promise,x.value);
},() => {
reject(promise,x.value);
})
}
if(x.state == 'fulfilled'){
return fulfill(promise,x.value);
}
if(x.state === 'rejected'){
return reject(promise,x.value)
}
}else if(isObject(x) || isFunction(x)){
let then;
try{
then = x.then;
}catch(e){
return reject(promise,e);
}
if(isFunction(then)){
let isCalled = false;
try{
then.call(x,function resolvePromise(y){
if(isCalled){
return;
}
isCalled = true;
resolve(promise,y);
},function rejectPromise(r){
if(isCalled){
return;
}
isCalled = true;
reject(promise,r)
});
}catch(e){
if(!ifCalled){
return reject(promise,e);
}
}
}else{
return fulfill(promise,x)
}
}else{
return fulfill(promise,x)
}
}
ES6 promise API
Promise構(gòu)造函數(shù)
構(gòu)造函數(shù)
new Promise(function(resolve,reject){
//rosolve(value)
//reject(reason)
})
說(shuō)明
- 函數(shù)作為參數(shù)
- resolve函數(shù)將promise狀態(tài)從pending變成resolved(fulfilled)
- reject函數(shù)將promise狀態(tài)從pending變成rejected
靜態(tài)方法
- Promise.resolve(param) : 等同于 new Promise(function(resolve,reject){resolve(param)})
- Promise.reject(param) : 等同于 new Promise(function(resolve,reject){reject(param)})
- Promise.all([p1,...,pn) : 輸入一組promise返回一個(gè)新的promise,全部promise都是fulfilled結(jié)果才是fulfilled狀態(tài)
- Promise.allSettled([p1,...,pn) : 輸入一組promise返回一個(gè)新的promise,全部promise狀態(tài)改變后結(jié)果promise變成fulfilled狀態(tài)
- Promise.race([p1,...,pn) : 輸入一組promise返回一個(gè)新的promise,結(jié)果promise的狀態(tài)跟隨第一個(gè)變化的promise狀態(tài)
實(shí)例方法
- promise.then(onFulfilled,onRejected) : promise狀態(tài)改變之后的回調(diào),返回新的promise對(duì)象
- promise.catch(function(reason){}) : t同promise.then(null,onRejected),promise狀態(tài)改為rejected的回調(diào)
- promise.finally(function(reason){//test} : 同promise.then(function(){//test},function(){//test}),不管promise狀態(tài)如何都會(huì)執(zhí)行
注意點(diǎn)
- then、catch返回的promise是新的promise,不是原來(lái)的promise.
- Promise對(duì)象的錯(cuò)誤會(huì)“冒泡”,直到被捕獲為止,錯(cuò)誤會(huì)被下一個(gè)catch語(yǔ)句捕獲。
Promise實(shí)踐
- 不要忘記catch捕捉錯(cuò)誤
- then方法中使用return
- 傳遞函數(shù)給then方法
- 不要把promise寫(xiě)成嵌套
題目
- 3秒之后亮一次紅燈,再過(guò)2秒亮一次綠燈,再過(guò)1秒亮一次黃燈,用promise實(shí)現(xiàn)多次交替亮燈的效果
拆解:
- 多少秒后亮某個(gè)顏色的燈
- 順序亮一批燈
- 循環(huán)順序亮一批燈
function light(color,second){
return new Promise(function(resolve,reject){
setTimeout(function(){
console.log(color);
resolve();
},second * 1000);
});
}
//[{color:xx,second:xx}]
function orderLights(list){
let promise = Promise.resolve();
list.forEach(item => {
promise = promise.then(function(){
return light(item.color,item.second);
});
});
promise.then(function(){
return orderLights(list);
})
}
orderLights([{
color:'red',
second:3,
},{
color:'green',
second:3,
},{
color:'yellow',
second:3,
}]);
課后習(xí)題
- 根據(jù)Promise/A+規(guī)范實(shí)現(xiàn)promise,使用promises-aplus/promises-tests插件驗(yàn)證
- 找一些promise的面試題