一個promise實例:
var getJSON = function(url) {var promise = new Promise(function(resolve, reject) {// XHR對象發現ajax請求var client = new XMLHttpReqeust();client.open("GET", url);client.onreadystatechange = handler;client.responseType = "json";client.setRequestHeader("Accept", "application/json");client.send();function hanlder(){if (this.readyState !== 4) {return;}if (this.status === 200) {resolve(this.response);} else {reject(new Error(this.statusText));}};});return promise;
}
getJSON("/posts.json").then(function(json) {console.log("Content: " + json);
}, function(error) {console.error("出錯了!', error);
});
上述在調用new Promise時,傳遞了一個函數function(resolve, reject),此函數在規范中被稱為exector執行器.
所以,首先:需傳入一個exector執行器:
function Promise(exector) {//...
}
確定Promise內部exector的作用:
可以看出原生的exector中傳入了2個參數,resolve和reject.第一個代表成功,第二個代表失敗.
function Promise(exector) {let self = this;this.value = undefined;this.reason = reason;// 執行成功function resolve(value) {self.value = value;}// 執行失敗function reject(reason) {self.reason = reason;}exector(resolve, reject);
}
添加狀態:
promise的執行過程是不可逆,因此需要一個status來記錄其狀態,初始時為padding,成功了為resolve,失敗了為reject
function Promise(exector) {let self = this;this.status = "padding";this.value = value;this.reason = reason;// 成功function resolve(value) {if(self.status === "padding") {self.value = value;self.status = "resolved";}}// 失敗function reject(reason) {if(self.status === "padding") {self.reason = reason;self.status = "reject";}}// 對異常的處理try {exector(resolve, reject);} catch(e) {reject(e)}
}
原型上添加then方法:
注意到Promise實例的使用是p.then(onFulfilled, onRejected),可以在前面定義的Promise的原型上添加then方法.
Promise.prototype.then = function(onFulfilled, onRejected) {let self = this;if(this.status === "resolved") {onFulfilled(self.value);}if(this.status === "rejected") {onRejected(self.value);}
}
新增2個數組完成異步操作:
上面編寫的Promise的調用是同步的,但一般都是異步使用Promise,故需在對Promise和其原型進行一定的修改.
如果異步,則處于padding狀態,將回調函數fn保存在數組中!
function Promise(exector) {let self = this;this.status = "padding";this.value = undefined;this.reason = undefined;// 存儲then中成功的回調函數this.onResolvedCallbacks = [];// 存儲then中失敗的回調函數this.onRejectedCallbacks = [];// 成功執行function resolve(value) {if(self.status === "padding") {self.value = value;self.status = "resolved";// 成功后遍歷then中成功的所有回調函數self.onResolvedCallbacks.forEach(fn => fn());}}// 失敗執行function reject(reason) {if(self.status === "padding") {self.reason = reason;self.status = "rejected";// 失敗后遍歷then中失敗的所有回調函數self.onRejectedCallbacks.forEach(fn => fn());}}// 對異常進行處理try {exector(resolve, reject);} catch(e) {reject(e)}
}// Promise.prototype.then
Promise.prototype.then = function(onFulfilled, onRejected) {let self = this;// 成功if (this.status === "resolved") {onFulfilled(self.value);}// 失敗if (this.status === "rejected") {onRejected(self.reason);}// paddingif (this.status === "padding") {// 推進onResolvedCallbacks數組this.onResolvedCallbacks.push( () => {onFulfilled(self.value);})this.onRejectedCallbacks.push( () => {onRejected(self.reason);})}
}
參考《ES6標準入門》(第3版) P276
參考 https://www.jianshu.com/p/4b126518c26d