從構造函數開始
- Promise就是一個類,在執行這個類的時候需要傳遞一個執行器進去,執行器會立即執行。
- Promise中有三種狀态 分别為:成功
失敗fulfilled
等待rejected
,一旦狀态确定就不可更改。pending
//Promise 類核心邏輯實作
const PENDING = 'pending';//等待
const FULFILLED = 'filfulled';//成功
const REJECTED = 'rejected';//失敗
class Promise {
//構造函數
constructor(executor){
//try catch為了捕獲執行器中的錯誤 進而抛出異常
try{
//執行器:立即執行
executor(this.resolve,this.reject)
}catch(e){
this.reject(e)
}
}
//promise狀态:先定義為peding,在resolve和reject中改變狀态
status = PENDING;
//成功之後的值
value = undefined;
//失敗後的原因
reason = undefined;
//成功回調函數隊列
successCallback = [];
//失敗回調函數隊列
failCallback = [];
}
module.exports = Promise
resolve屬性的定義
resolve屬性用來修改Promise的狀态:pending => fulfilled
//構造函數中
resolve = value =>{
//如果不是等待,則阻止程式向下執行
if(this.status !=== 'pending') return;
//将狀态更改為成功
this.status = FULFILLED
//儲存成功之後的值
this.value = value
//判斷成功回調是否存在 如果存在 => 調用:調用完後删除并傳回第一個回調的值
while(this.successCallback.length) this.successCallback.shift()()
}
reject屬性的定義
reject屬性用來修改Promise的狀态:pending => rejected
//構造函數中
reject = reason => {
//如果狀态不是等待,阻止程式向下執行
if(this.status !== 'pending') return;
//将狀态更改為失敗
this.status = REJECTED
//儲存失敗之後的原因
this.reason = reason
//判斷失敗回調是否存在 如果存在 調用
white(this.failCallback.length) this.failCallback.shift()()
}
then方法的實作
- then方法是被定義在原型對象中的。
- then支援兩個參數,分别是成功和失敗的回調,而且這兩個參數可傳可不傳。
- then方法内部做的事情就是判斷狀态:如果狀态是成功,調用成功的回調函數 ,如果狀态是失敗,則調用失敗回調函數。
- 因為有異步任務的情況,并且支援多個回調,是以我們需要對回調函數采用資料進行儲存,是以上面定義了失敗和成功的回調函數隊列。
- then的傳回結果也是Promise對象
//構造函數中
then(successCallback,failCallback){
//當調用then方法的時候不傳遞參數,則Promise狀态會依次向後傳遞,直到傳遞給有回調的then方法
successCallback = successCallback ? successCallback : value => value
failCallback = failCallback ? failCallback : reason => { throw reason }
let promise2 = new Promise((resolve,reject) => {
let that = this
if(this.status === FULFILLED){
//為了變為異步操作
setTimeout(()=>{
//try catch為了捕獲錯誤,抛出異常
try{
let x = successCallback(this.value)
//判斷x的值是普通值還是Promise對象:如果是普通值,直接調用resolve / 如果是Promise對象,檢視Promise對象傳回的結果。
//然後再根據Promise對象傳回的結果,決定調用resolve 還是調用reject
resolvePromise(promise2,x,resolve,reject)
}catch(e){
reject(e)
}
},0)
}else {
//有異步任務時:等待
//将成功回調和失敗回調儲存起來
this.successCallback.push(()=>{
//為了變為異步操作
setTimeout(()=>{
//try catch為了捕獲錯誤,抛出異常
try{
let x = successCallback(this.value)
//判斷x的值是普通值還是Promise對象:如果是普通值,直接調用resolve / 如果是Promise對象,檢視Promise對象傳回的結果。
//然後再根據Promise對象傳回的結果,決定調用resolve 還是調用reject
resolvePromise(promise2,x,resolve,reject)
}catch(e){
reject(e)
}
},0)
});
this.failCallback.push(()=>{
//為了變為異步操作
setTimeout(()=>{
//try catch為了捕獲錯誤,抛出異常
try{
let x = successCallback(this.value)
//判斷x的值是普通值還是Promise對象:如果是普通值,直接調用resolve / 如果是Promise對象,檢視Promise對象傳回的結果。
//然後再根據Promise對象傳回的結果,決定調用resolve 還是調用reject
resolvePromise(promise2,x,resolve,reject)
}catch(e){
reject(e)
}
},0)
})
}
})
return promise2;
}
function resolvePromise(promise2,x,resolve,reject){
if(promise2 === x){
return reject(new TypeError('Chaining cycle detected for promise #<Promise>'))
}
if(x instanceof Promise){
//Promise對象
x.then(resolve,reject)
}else {
//普通值
resolve(x)
}
}
catch方法的實作
- catch方法用來處理目前這個Promise最終的狀态為失敗的情況。
- 當我們調用then方法時 是可以不傳遞失敗回調的 那麼失敗回調就會被catch捕獲并傳入catch方法的回調函數。
- catch不是靜态方法,需要定義在Promise的原型上
//構造函數中
catch(failCallback){
return this.then(undefined,failCallback)
}
finally方法的實作
- 無論目前的這個Promise對象是成功的還是失敗的 finally當中的函數總會被執行一次。
- finally方法的後面我們可以鍊式調用then方法 來得到目前這個Promise最終傳回的結果。
- finally不是靜态方法,需要定義在Promise的原型上
- 需要實作鍊式調用
//構造函數中
finally(callback){
//調用then方法來得到目前Promise的狀态
//因為then方法就傳回一個Promise,是以直接return
//要等待異步操作完成後,後面的then才能執行
return this.then(value => {
//如果callback傳回值是普通值,那麼就轉換成Promise等待執行完成,後面的then再執行,如果傳回的是Promise 還是等待執行完成在執行
return Promise.resolve(callback()).then(()=>value)
},reason => {
return Promise.resolve(callback()).then(()=>{ throw reason })
})
}
Promise.resolve方法的實作
- Promise.resolve 的作用就是将裡面的值轉化為promise對象。
- Promise.resolve 是一個靜态方法。
//構造函數中
static resolve(value){
//判斷是普通值還是Promise對象,如果是Promise對象就原封不動的放回出去,如果是普通值,那就建立一個Promise将普通值包裹進去傳回出去。
if(value instanceof Promise) return value;
return new Promise(resolve => resolve(value));
}
Promise.reject方法的實作
- Promise.reject()方法的參數,會原封不動地作為reject的理由,變成後續方法的參數。這一點與Promise.resolve方法不一緻
- Promise.reject是一個靜态方法。
// Promise.reject()方法的參數,會原封不動地作為reject的理由,變成後續方法的參數。
// 這一點與Promise.resolve方法不一緻
static reject(reason) {
return new Promise((undefined, reject) => reject(reason));
}
Promise.all方法的實作
- Promise.all方法是解決異步并發問題的,它允許我們按照異步調用的順序來執行異步方法。
- Promise.all是一個靜态方法,接收一個數組作為參數。
- Promise.all 後面也可以.then鍊式調用。
//構造函數中
static all(array){
//準備一個結果數組
let result = [];
let index = 0;
//Promise.all 後面也可以.then 是以先傳回個Promise對象
return new Promise((resolve,reject) => {
//向結果數組中添加傳回值
function addData(key,value){
result[key] = value
index ++;
//for循環是同步執行循環體的,是以我們必須等待異步操作完成之後才能去傳回結果
// 如果index 等于 數組的長度,代表所有的操作已經完畢,就可以傳回結果了
if(index === array.length){
resolve(result);
}
}
//通過循環的方式,循環進來的資料,在循環過程中判斷了循環目前值,判斷其是普通值還是Promise對象
for(let i=0;i<array.length;i++){
let current = array[i]
//判斷目前的值是普通值還是Promise對象
if(current instanceof Promise){
//注:在執行過程中别忘記有異步任務,for循環是不會等待異步操作的,是以當我們調用resolve的時候,還沒有執行完,是以結果中會有空值。
//Promise對象:先執行Promise對象,如果執行成功調用addData方法,反之reject()
current.then(value => addData(i,value),reason => reject(reason))
}else {
//普通值:對應放入結果數組中
addData(i,array[i])
}
}
})
}
Promise.race方法的實作
// race方法
static race (array) {
// race方法,取數組中第一個傳回的結果,無論成功或者失敗
return new Promise((resolve, reject) => {
array.forEach(current => {
if (current instanceof Promise) {
// promsie對象,傳回成功或者失敗的結果
current.then(value => resolve(value), reason => reject(reason))
} else {
// 普通值 ,直接傳回
resolve(current)
}
})
})
}
完整代碼
const PENDING = 'pending';//等待
const FULFILLED = 'filfulled';//成功
const REJECTED = 'rejected';//失敗
class Promise {
constructor(executor){
try{
executor(this.resolve,this.reject)
}catch(e){
this.reject(e)
}
}
status = PENDING;
value = undefined;
reason = undefined;
successCallback = [];
failCallback = [];
resolve = value =>{
if(this.status !=== 'pending') return;
this.status = FULFILLED
this.value = value
while(this.successCallback.length) this.successCallback.shift()()
}
reject = reason => {
if(this.status !== 'pending') return;
this.status = REJECTED
this.reason = reason
white(this.failCallback.length) this.failCallback.shift()()
}
then(successCallback,failCallback){
successCallback = successCallback ? successCallback : value => value
failCallback = failCallback ? failCallback : reason => { throw reason }
let promise2 = new Promise((resolve,reject) => {
let that = this
if(this.status === FULFILLED){
setTimeout(()=>{
try{
let x = successCallback(this.value)
resolvePromise(promise2,x,resolve,reject)
}catch(e){
reject(e)
}
},0)
}else {
this.successCallback.push(()=>{
setTimeout(()=>{
try{
let x = successCallback(this.value)
resolvePromise(promise2,x,resolve,reject)
}catch(e){
reject(e)
}
},0)
});
this.failCallback.push(()=>{
setTimeout(()=>{
try{
let x = successCallback(this.value)
resolvePromise(promise2,x,resolve,reject)
}catch(e){
reject(e)
}
},0)
})
}
})
return promise2;
}
function resolvePromise(promise2,x,resolve,reject){
if(promise2 === x){
return reject(new TypeError('Chaining cycle detected for promise #<Promise>'))
}
if(x instanceof Promise){
x.then(resolve,reject)
}else {
resolve(x)
}
}
catch(failCallback){
return this.then(undefined,failCallback)
}
finally(callback){
return this.then(value => {
return Promise.resolve(callback()).then(()=>value)
},reason => {
return Promise.resolve(callback()).then(()=>{ throw reason })
})
}
static resolve(value){
if(value instanceof Promise) return value;
return new Promise(resolve => resolve(value));
}
static reject(reason) {
return new Promise((undefined, reject) => reject(reason));
}
static race (array) {
return new Promise((resolve, reject) => {
array.forEach(current => {
if (current instanceof Promise) {
current.then(value => resolve(value), reason => reject(reason))
} else {
resolve(current)
}
})
})
}
static all(array){
let result = [];
let index = 0;
return new Promise((resolve,reject) => {
function addData(key,value){
result[key] = value
index ++;
if(index === array.length){
resolve(result);
}
}
for(let i=0;i<array.length;i++){
let current = array[i]
if(current instanceof Promise){
current.then(value => addData(i,value),reason => reject(reason))
}else {
addData(i,array[i])
}
}
})
}
}
module.exports = Promise