ES6 規定,
Promise
對象是一個構造函數,用來生成
Promise
執行個體。
下面代碼創造了一個
Promise
執行個體。
const promise=new Promise(function(resolve,reject){
if (/* 異步操作成功 */){
resolve(value);
} else {
reject(error);
}
})
Promise
構造函數接受一個函數作為參數,該函數的兩個參數分别是
resolve
和
reject
。它們是兩個函數,由 JavaScript 引擎提供,不用自己部署。
resolve
函數的作用是,将
Promise
對象的狀态從“未完成”變為“成功”(即從 pending 變為 resolved),在異步操作成功時調用,并将異步操作的結果,作為參數傳遞出去;
reject
函數的作用是,将
Promise
對象的狀态從“未完成”變為“失敗”(即從 pending 變為 rejected),在異步操作失敗時調用,并将異步操作報出的錯誤,作為參數傳遞出去。
Promise.prototype.then()
Promise 執行個體具有
then
方法,也就是說,
then
方法是定義在原型對象
Promise.prototype
上的。
作用是為 Promise 執行個體 添加 狀态改變時的回調函數。
第一個參數是
resolved
狀态的回調函數,第二個參數(可選)是
rejected
狀态的回調函數。
then
方法傳回的是一個新的
Promise
執行個體(注意,不是原來那個
Promise
執行個體)。是以可以采用鍊式寫法,即
then
方法後面再調用另一個
then
方法。
//Pending(等待、進行中) ---> Resolve(完成,fullFilled) ---> Reject(拒絕,失敗)
var p1 = new Promise(function(resolve,reject){
resolve(1); // 成功了
// reject(2); // 失敗了
});
// 接收成功和失敗的資料,通過then來傳遞
// then也是傳回一個promise對象,會繼續往下傳遞資料,傳遞給下一個then
p1.then(function(value){
// resolve
console.log(value);
return value + 1; // 1
alert(`成功了:${value}`);
},function(value){
// reject
alert(`失敗了:${value}`);
}).then(function(value){
console.log(value); // 2
});
Promise.prototype.catch()
用于指定發生錯誤時的回調函數。
var p1 = new Promise(function(resolve,reject){
//resolve(1); // 成功了
reject(2); // 失敗了
});
p1.then(function(value){
// resolve
console.log(value);
return value + 1;
}).catch(function(value){
console.log(value); //2
return value + 1;
}).then(function(value){
console.log(value); // 3
});
then
方法指定的回調函數,如果運作中抛出錯誤,也會被
catch
方法捕獲。
//catch捕獲異常錯誤
var p1 = new Promise(function(resolve,reject){
resolve('成功了');
});
p1.then(function(value){
console.log(value); // 成功了
// throw是用來抛錯誤的
throw '發生了點小意外';
}).catch(function(e){
// catch用來捕獲這個錯誤的 ---> 追蹤
console.log(e); // 發生了點小意外
});
如果 Promise 狀态已經變成resolved,再抛出錯誤是無效的。
const promise = new Promise(function(resolve, reject) {
resolve('ok');
throw new Error('test');
});
promise
.then(function(value) { console.log(value) })
.catch(function(error) { console.log(error) });
// ok
一般來說,不要在
then
方法裡面定義 Reject 狀态的回調函數(即
then
的第二個參數),總是使用
catch
方法。
Promise.all()
Promise.all
方法用于将多個 Promise 執行個體,包裝成一個新的 Promise 執行個體。
var p=Promise.all([p1,p2,p3])
//Promise.all([p1,p2,p3,...]); 所有的promise對象,都正确,才走成功
//否則,隻要有一個錯誤,就走失敗
var p1 = Promise.resolve(1);
var p2 = Promise.reject(0);
Promise.all([true,p1,p2]).then(function(obj){
console.log(`成功了:${obj}`);
},function(obj){
console.log(`失敗了:${obj}`);
});
Promise.race()
var p=Promise.race([p1,p2,p3])
// race ---> 傳回的也是一個promise對象
//最先執行的的promise結果,哪個最快我用哪個
var p1 = new Promise(function(resolve,reject){
setTimeout(resolve,50,'one');
});
var p2 = new Promise(function(resolve,reject){
setTimeout(resolve,100,'two');
});
Promise.race([p1,p2]).then(function(val){
console.log(val);
});
Promise.resolve()
有時需要将現有對象轉為 Promise 對象,
Promise.resolve
方法就起到這個作用。
Promise.resolve
等價于下面的寫法。
Promise.resolve('foo')
// 等價于
new Promise(resolve => resolve('foo'))
應用
加載圖檔
将圖檔的加載寫成一個
Promise
,一旦加載完成,
Promise
的狀态就發生變化。
const preloadImage = function (path) {
return new Promise(function (resolve, reject) {
const image = new Image();
image.onload = resolve;
image.onerror = reject;
image.src = path;
});
};
//Generator 函數 與 Promise結合