Promise對象的特點:
1、對象的狀態不受外界影響。promise對象代表一個異步操作,有3種狀態:Pending(進行中)、Fulfilled(已成功)、Rejected(已失敗)。
2、一旦狀態改變就不會再變。因此它的狀態改變只有兩種可能:Pending到Fulfilled,Pending到Rejected。
基本用法
Promise構造函數接受一個函數作爲參數,該參數的兩個參數分別是resolve和reject,他們是兩個函數。
生成實例後,可以用then方法分別指定Resolved狀態和Rejected狀態的回調函數。then方法可以接收兩個參數,第一個是promise對象的狀態變爲Resolved時調用,第二個是狀態變爲Rejected狀態時調用,第二個參數可選,此時可以調用catch方法,catch除了狀態變爲Rejected時會調用以外,也會捕獲Promise對象中的錯誤。建議使用catch,而不是使用then的第二個參數。
var p = new Promise(resolve,reject){
console.log('promise');
if(/*異步操作成功*/){
resolve(value);
}else{
reject(reason);
}
}
p.then(function(value){
//狀態變爲resolve時的回調
console.log(value)
},function(error){
//狀態變爲reject時的回調
console.log(error)
});
//使用catch
p.then(function(value){
console.log(value)
}).catch(function(error){
console.log(error)
})
TIPS:promise裏的代碼是同步執行,then裏的回調是異步執行
Promise.prototype.then()、Promise.prototype.catch()
返回一個新的promise對象,可以繼續調用這個新對象的then或catch方法,其參數爲第一個then方法或catch方法的返回值。
function timeout(ms) {
return new Promise((resolve, reject) => {
setTimeout(() => {
resolve('resolve');
}, ms);
});
}
async function asyncPrint(value, ms) {
timeout(ms)
.then(res => {
return res;
})
.then(res => {
console.log(
'第一個then方法返回promise對象,其return的值爲第二個then回調的參數::' +
res
);
});
}
asyncPrint('hello world', 1000);
catch未返回Promise.reject時,此新promise對象會走到then回調裏:
function timeout(ms) {
return new Promise((resolve, reject) => {
setTimeout(() => {
reject('reject');
}, ms);
});
}
async function asyncPrint(value, ms) {
timeout(ms)
.then(res => {
return res;
})
.catch(error => error)
.then(res => {
console.log(
'catch方法返回promise對象,其return的值爲第二個then回調的參數::' +
res
);
});
}
asyncPrint('hello world', 1000);
catch返回Promise.reject時,此新promise對象會走到catch回調裏:
//catch返回了reject錯誤,因此需要後面調用catch方法捕獲reject錯誤,不寫catch會報錯
function timeout(ms) {
return new Promise((resolve, reject) => {
setTimeout(() => {
reject('reject');
}, ms);
});
}
async function asyncPrint(value, ms) {
timeout(ms)
.then(res => {
return res;
})
.catch(error => {
return Promise.reject(
'返回reject錯誤,被後面的catct捕獲::' + error
);
})
.catch(error => {
console.log(error);
});
}
asyncPrint('hello world', 1000);
Promise.all()
Promise.all()方法用於將多個Promise實例包裝成一個新的Promise實例,接收一個數組做爲參數。
var p = Promise.all([p1,p2,p3]);
如上例子,p1/p2/p3都是promise對象,p的狀態由他們共同決定:
1、只有當p1/p2/p3都變成Fulfilled時,p的狀態纔會變成Fulfilled,p1/p2/p3的返回值組成一個數組,傳遞給p的回調函數
2、只要p1/p2/p3有一個變成Rejected,p的狀態就會變成Rejected,此時第一個變成Rejected的實例的返回值會傳遞給p的回調函數
TIPS:如果p1/p2/p3自身定義了catch方法,那麼它被rejected時並不會觸發Promise.all()的catch方法,如下:
var p1 = new Promise((resolve,reject) => {
resolve();
})
.then(value => value)
.catch(e => e);
var p2 = new Promise((resolve,reject) => {
throw new Error('報錯了');
})
.then(value => value)
.catch(e => e);
var p = Promise.all([p1,p2])
.then(value => console.log(value))
.catch(e => console.log(e))
//['hello',Error:報錯了]
以上代碼:p1會resolved,p2首先會rejected,但是p2有自己的catch方法,該方法返回一個新的Promise實例,p2實際上指向的是這個實例,該實例執行完catch後也會變成resolved,導致p對象裏的兩個實例都會resolved,因此會調用p對象裏的then方法指定的回調函數,而不是catch方法
Promise.resolve()、Promise.reject():
有時需要將現有對象轉化爲Promise對象,以上兩個方法返回一個狀態爲resolve或reject的promise對象。
創建一個Promise的類
class PromiseNew {
constructor(executer) {
//構造函數constructor裏面是個執行器
this.status = 'pending'; //默認的狀態 pending
this.value = undefined; //成功的值默認undefined
this.reason = undefined; //失敗的值默認undefined
//狀態只有在pending時候才能改變
let resolveFn = value => {
//判斷只有等待時才能resolve成功
if (this.status === 'pending') {
this.status = 'resolve';
this.value = value;
}
};
//判斷只有等待時才能reject失敗
let rejectFn = reason => {
if (this.status === 'pending') {
this.status = 'reject';
this.reason = reason;
}
};
try {
//把resolve和reject兩個函數傳給執行器executer
executer(resolveFn, rejectFn);
} catch (e) {
rejectFn(e); //失敗的話進catch
}
}
then(onFufilled, onReject) {
//如果狀態成功調用onFufilled
if (this.status === 'resolve') {
onFufilled(this.value);
}
//如果狀態失敗調用onReject
if (this.status === 'reject') {
onReject(this.reason);
}
}
}