我如何實現Promise

用法

new Promise((resolve, reject) => {
	//異步成功執行resolve,不然執行reject
}).then((res) => {
	//resolve觸發第一個回調函數執行 
}, (err) => {
	//reject觸發第二個回調函數執行
}).then(res => {
//須要保證then方法返回的依然是promise
//這樣才能實現鏈式調用
}).catch(reason => {

});
//等待全部的promise都成功執行then,
//反之只要有一個失敗就會執行catch
Promise.all([promise1, ...]).then();

複製代碼

1、小試牛刀

初步實現Promise:promise

1.實現三種狀態:‘pending’, 'fulfilled', 'rejected'dom

2.可以實現then方法兩種回調函數的處理異步

//promise.js
class Promise{
  //傳一個異步函數進來
  constructor(excutorCallBack){
    this.status = 'pending';
    this.value = undefined;
    this.fulfillAry = [];
    this.rejectedAry = [];
    //=>執行Excutor
    let resolveFn = result => {
      if(this.status !== 'pending') return;
      let timer = setTimeout(() => {
        this.status = 'fulfilled';
        this.value = result;
        this.fulfillAry.forEach(item => item(this.value));
      }, 0);
    };
    let rejectFn = reason => {
      if(this.status !== 'pending')return;
      let timer = setTimeout(() => {
        this.status = 'rejected';
        this.value = reason;
        this.rejectedAry.forEach(item => item(this.value))
      })
    };
    try{
      //執行這個異步函數
      excutorCallBack(resolveFn, rejectFn);
    } catch(err) {
      //=>有異常信息按照rejected狀態處理
      rejectFn(err);
    }
  }
  then(fulfilledCallBack, rejectedCallBack) {
    //resolve和reject函數其實一個做爲微任務
    //所以他們不是當即執行,而是等then調用完成後執行
    this.fulfillAry.push(fulfilledCallBack);
    this.rejectedAry.push(rejectedCallBack);
    //一頓push事後他們被執行
  }
}

module.exports = Promise;

複製代碼

測試以下:函數

let Promise = require('./promise');

let p1 = new Promise((resolve, reject) => {
  setTimeout(() => {
    Math.random()<0.5?resolve(100):reject(-100);
  }, 1000)
}).then(res => {
  console.log(res);
}, err => {
  console.log(err);
})

複製代碼

2、 完成鏈式效果

最大的難點在於鏈式調用的實現,具體來講就是then方法的實現。測試

//then傳進兩個函數
  then(fulfilledCallBack, rejectedCallBack) {
    //保證二者爲函數
    typeof fulfilledCallBack !== 'function' ? fulfilledCallBack = result => result:null;
    typeof rejectedCallBack !== 'function' ? rejectedCallBack = reason => {
      throw new Error(reason instanceof Error? reason.message:reason);
    } : null
    //返回新的Promise對象,後面稱它爲「新Promise」
    return new Promise((resolve, reject) => {
      //注意這個this指向目前的Promise對象,而不是新的Promise
      //再強調一遍,很重要:
      //目前的Promise(不是這裏return的新Promise)的resolve和reject函數其實一個做爲微任務
      //所以他們不是當即執行,而是等then調用完成後執行
      this.fulfillAry.push(() => {
        try {
          //把then裏面的方法拿過來執行
          //執行的目的已經達到
          let x = fulfilledCallBack(this.value);
          //下面執行以後的下一步,也就是記錄執行的狀態,決定新Promise如何表現
          //若是返回值x是一個Promise對象,就執行then操做
          //若是不是Promise,直接調用新Promise的resolve函數,
          //新Promise的fulfilAry如今爲空,在新Promise的then操做後.新Promise的resolve執行
          x instanceof Promise ? x.then(resolve, reject):resolve(x);
        }catch(err){
          reject(err)
        }
      });
      //如下同理
      this.rejectedAry.push(() => {
        try {
          let x = this.rejectedCallBack(this.value);
          x instanceof Promise ? x.then(resolve, reject):resolve(x);
        }catch(err){
          reject(err)
        }
      })
    }) ;
  }
複製代碼

測試用例:ui

let p1 = new Promise((resolve, reject) => {
  setTimeout(() => {
    Math.random()<0.5?resolve(100):reject(-100);
  }, 1000)
})

let p2 = p1.then(result => {
  //執行then返回的是一個新的Promise
  return result + 100;
})
let p3 = p2.then(result => {
  console.log(result);
}, reason => {
  console.log(reason)
})
複製代碼

簡單畫圖來模擬一下鏈式調用的內部流程: this

在這裏插入圖片描述
有了then方法,catch天然而然調用便可:

catch(rejectedCallBack) {
    return this.then(null, rejectedCallBack);
  }
複製代碼

3、Promise.all()

接下來實現Promise.all()spa

//爲類的靜態方法,而不是在原型上
static all(promiseAry = []) {
    let index = 0, 
        result = [];
    return new Promise((resolve, reject) => {
      for(let i = 0; i < promiseAry.length; i++){
        promiseAry[i].then(val => {
          index++;
          result[i] = val;
          if( index === promiseAry.length){
            resolve(result)
          }
        }, reject);
      }
    })
  }
複製代碼

4、Promise.race()

接下來是race方法code

static race(promises) {
  return new Promise((resolve, reject) => {
    if (promises.length === 0) {
      return;
    } else {
      for(let i = 0; i < promises.length; i++){
        promises[i].then(val => {
            resolve(result);
            return;
          }
        }, reject);
      }
    }
  });
}
複製代碼

5、Promise.resolve()

static resolve (value) {
    if (value instanceof Promise) return value
    return new Promise(resolve => resolve(value))
}
複製代碼

6、Promise.reject()

static reject (value) {
    return new Promise((resolve, reject) => reject(value))
}
複製代碼

完整代碼

如今手寫一個簡陋可是功能較爲完備的Promise就大功告成了。cdn

class Promise{
  constructor(excutorCallBack){
    this.status = 'pending';
    this.value = undefined;
    this.fulfillAry = [];
    this.rejectedAry = [];
    //=>執行Excutor
    let resolveFn = result => {
      if(this.status !== 'pending') return;
      let timer = setTimeout(() => {
        this.status = 'fulfilled';
        this.value = result;
        this.fulfillAry.forEach(item => item(this.value));
      }, 0);
    };
    let rejectFn = reason => {
      if(this.status !== 'pending')return;
      let timer = setTimeout(() => {
        this.status = 'rejected';
        this.value = reason;
        this.rejectedAry.forEach(item => item(this.value))
      })
    };
    try{
      excutorCallBack(resolveFn, rejectFn);
    } catch(err) {
      //=>有異常信息按照rejected狀態處理
      rejectFn(err);
    }
  }
  then(fulfilledCallBack, rejectedCallBack) {
    typeof fulfilledCallBack !== 'function' ? fulfilledCallBack = result => result:null;
    typeof rejectedCallBack !== 'function' ? rejectedCallBack = reason => {
      throw new Error(reason instanceof Error? reason.message:reason);
    } : null

    return new Promise((resolve, reject) => {
      this.fulfillAry.push(() => {
        try {
          let x = fulfilledCallBack(this.value);
          x instanceof Promise ? x.then(resolve, reject ):resolve(x);
        }catch(err){
          reject(err)
        }
      });
      this.rejectedAry.push(() => {
        try {
          let x = this.rejectedCallBack(this.value);
          x instanceof Promise ? x.then(resolve, reject):resolve(x);
        }catch(err){
          reject(err)
        }
      })
    }) ;
  }
  catch(rejectedCallBack) {
    return this.then(null, rejectedCallBack);
  }
  static all(promiseAry = []) {
    let index = 0, 
        result = [];
    return new Promise((resolve, reject) => {
      for(let i = 0; i < promiseAry.length; i++){
        promiseAry[i].then(val => {
          index++;
          result[i] = val;
          if( index === promiseAry.length){
            resolve(result)
          }
        }, reject);
      }
    })
  }
 static race(promiseAry) {
  return new Promise((resolve, reject) => {
    if (promiseAry.length === 0) {
      return;
    }
    for (let i = 0; i < promiseAry.length; i++) {
      promiseAry[i].then(val => {
        resolve(val);
        return;
      }, reject);
    }     
  })
}
static resolve (value) {
    if (value instanceof Promise) return value
    return new Promise(resolve => resolve(value))
}
static reject (value) {
    return new Promise((resolve, reject) => reject(value))
}
}

module.exports = Promise;

複製代碼
相關文章
相關標籤/搜索