Promise
是異步編程的一種解決方案,ES6新增的一個對象,用來傳遞異步操做的消息。它表明了某個將來纔會知道結果的事件(一般是一個異步操做),而且這個事件提供統一的 API,可供進一步處理。編程
Promise
有如下兩個特色:數組
(1)Promise
的狀態不受外界影響。Promise
翻譯過來是承諾的意思,這個承諾會在將來有一個確切的答覆,而且該承諾有三種狀態,分別是:等待中pending
、已完成 resolved
、已失敗rejected
。它表明一個異步操做,只有異步操做的結果能夠決定當前是哪種狀態,任何其餘操做都沒法改變這個狀態。緩存
(2)Promise
一旦由等待狀態變成爲其餘狀態就永遠不能更改成其餘狀態了。也就是說,當狀態從 Pending
變爲 Resolved
或者 Rejected
後,狀態就不能更改了。框架
new Promise((resolve, reject) => {
resolve('resolve')
reject('reject') // 這個reject無效
})
複製代碼
當咱們在構造 Promise
的時候,構造函數內部的代碼是當即執行的:異步
new Promise((resolve, reject) => {
console.log(1);
resolve('resolve')
})
console.log(2);
複製代碼
Promise
的鏈式調用:異步編程
new Promise(function(resolve, reject){
resolve(1);
}).then(function(data){
console.log(data);
return new Promise(function(resolve, reject){
resolve(2);
})
}).then(function(data){
console.log(data);
}).catch(function(err){
console.log(err);
})
複製代碼
Promise
很好地解決了回調地獄的問題,使代碼能夠變得更加簡潔優雅。函數
Promise
也存在一些缺點:(1) 它一旦新建就會當即執行,沒法中途取消;(2) 錯誤是須要經過回調函數捕獲。ui
首先,建立三個表示狀態的常量:this
const PENDING = 'pending';
const RESOLVED = 'resolved';
const REJECTED = 'rejected';
複製代碼
搭建構造函數的框架:spa
function myPromise(fn) { // 傳入的是一個函數
// 定義一個常量that來緩存當前的this對象
const that = this;
// 初始狀態是pending
that.status = PENDING;
// 定義一個變量來保存resolve或者reject傳入的值
that.param = null;
// 定義兩個數組來記錄異步操做以後回來執行的函數(即保存then中的回調函數,等狀態改變時執行)
that.resolvedCallBacks = []; // 狀態轉爲成功以後執行的函數
that.rejectedCallBacks = []; // 狀態轉爲失敗以後執行的函數
// 定義resolve函數
function resolve() {
}
// 定義reject函數
function reject() {
}
// 執行fn函數
fn();
}
複製代碼
下面來完善resolve
和reject
函數:
// 定義resolve函數
function resolve(param) {
// 只有狀態爲初始狀態時才執行
if (that.status === PENDING) {
that.status = RESOLVED; // 執行以後狀態改成成功
that.param = param; // 記錄傳入的參數
// 遍歷回調函數並執行
that.resolvedCallBacks.map(function(callback){
callback && callback(that.param);
})
}
}
// 定義reject函數
function reject(param) {
// 只有狀態爲初始狀態時才執行
if (that.status === PENDING) {
that.status = REJECTED; // 執行以後狀態改成失敗
that.param = param; // 記錄傳入的參數
// 遍歷回調函數並執行
that.resolvedCallBacks.map(function(callback){
callback && callback(that.param);
})
}
}
複製代碼
執行 fn
函數時,把 resolve
和 reject
當作參數傳入,捕捉到錯誤後執行 reject
函數
// 執行fn函數
try {
fn(resolve, reject);
} catch(e) {
reject(e);
}
複製代碼
接下來實現 then
函數:
// then函數有兩個參數onFulfilled, onRejected(參數爲函數)
// 當前實例狀態變成成功狀態時,onFulfilled做爲回調函數被調用
// 當前實例狀態變成失敗狀態時,onRejected做爲回調函數被調用
myPromise.prototype.then = function(onFulfilled, onRejected) {
const that = this;
// 當狀態爲初始狀態時,把對應函數保存到對應回調函數數組中
if (that.status === PENDING) {
that.resolvedCallBacks.push(onFulfilled);
that.rejectedCallBacks.push(onRejected);
}
// 當狀態爲成功狀態時,執行onFulfilled
if (that.status === RESOLVED) {
onFulfilled(that.param);
}
// 當狀態爲成功狀態時,執行onFulfilled
if (that.status === REJECTED) {
onRejected(that.param);
}
}
複製代碼
以上就是簡易版的 Promise
實現了,最後來簡單的運行一下:
new myPromise(function(resolve, reject){
resolve(1);
// reject(2);
}).then(function(data) {
console.log(data);
}, function(err) {
console.log(err);
})
複製代碼