簡要介紹:Promise容許咱們經過鏈式調用的方式來解決「回調地獄」的問題,特別是在異步過程當中,經過Promise能夠保證代碼的整潔性和可讀性。promise
本文主要介紹一下Promise/A+規範,並在此規範的基礎上,本身實現一個Promise。瀏覽器
在瞭解Promise規範以前,咱們知道主流的高版本瀏覽器已經支持ECMA中的Promise.異步
建立一個promise實例:函數
let p1 = new Promise((resolve, reject) => { setTimeout(() => { resolve("success"); }, 3000); console.log("this is a promise"); }); p1.then(value => { console.log(value); }); // 輸出: // 立馬打印:this is a promise // 延遲3000ms後打印:success
上述是一個promise的實例,輸出內容爲,「this is a promise」,延遲3000ms後,輸出"success"。this
從上述的例子能夠看出,promise方便處理異步操做。此外promise還能夠鏈式的調用:prototype
let p2 = new Promise((resolve, reject) => { resolve(); }); p2.then(...).then(...).then(...);
此外Promise除了then方法外,還提供了Promise.resolve、Promise.all、Promise.race等等方法。code
Promise/A+規範大體有如下內容:對象
1.術語
(1)"promise"是一個對象或者函數,該對象或者函數有一個then方法
(2)"thenable"是一個對象或者函數,用來定義then方法
(3)"value"是promise狀態成功時的值
(4)"reason"是promise狀態失敗時的值
咱們明確術語的目的,是爲了在本身實現promise時,保持代碼的規範性原型
2.要求
(1)一個promise必須有3個狀態,pending,fulfilled(resolved),rejected。
當處於pending狀態的時候,能夠轉移到fulfilled(resolved)或者rejected狀態。當處於fulfilled(resolved)狀態或者rejected狀態的時候,就不可變。
promise英文譯爲承諾,也就是說promise的狀態一旦發生改變,就永遠是不可逆的。it
(2)一個promise必須有一個then方法,then方法接受兩個參數:
promise1.then(onFulfilled, onRejected);
其中onFulfilled方法表示狀態從pending —> fulfilled(resolved)時所執行的方法,而onRejected表示狀態從pending —> rejected所執行的方法。
(3)爲了實現鏈式調用,then方法必須返回一個promise
promise2 = promise1.then(onFulfilled, onRejected);
瞭解了Promise/A+規範以後,下面咱們來看如何實現一個Promise。
首先構造一個myPromise函數,關於全部變量和函數名,應該與規範中保持相同。
function myPromise(constructor) { let self = this; self.status = 'pending'; self.value = undefined; // 成功時的值 self.reason = undefined; // 失敗時的值 function resolve (value) { // 1.確保狀態只能由 pending 改成 resolved if (self.status === 'pending') { self.value = value; self.status = 'resolved'; } } function reject (reason) { // 2.確保狀態只能由 pending 改成 rejected if (self.status === 'pending') { self.reason = reason; self.status = 'rejected'; } } try { constructor(resolve, reject); } catch(e) { reject(e); } }
同時,須要在myPromise的原型上定義鏈式調用的then方法:
myPromise.prototype.then = function (onFullfilled, onRejected) { let self = this; switch (self.status) { case 'resolved': onFullfilled(self.value); break; case 'rejected': onRejected(self.reason); break; } };
上述就是一個初始版本的myPromise,在myPromise裏發生狀態改變,而後在相應的then方法裏面根據不一樣的狀態能夠執行不一樣的操做。
let mp = new myPromise(function (resolve, reject) { resolve(1); // reject('err msg'); }); mp.then(function (res) { console.log(res); }, function (err) { console.log(err); }); // 輸出 1
可是這裏myPromise沒法處理異步的resolve。好比:
let mp1 = new myPromise(function (resolve, reject) { setTimeout(() => { resolve(2); }, 2000); }); mp1.then(function (res) { console.log(res); }); // 無輸出
...