手寫promise,Promise.all(),Promise.race()

手寫promise

const PENDING = 'pending'
const RESOLVED = 'resolved'
const REJECTED = 'rejected'

function MyPromise(fn) {
  // 保存初始化狀態
  var self = this

  // 初始化狀態
  this.state = PENDING

  // 用於保存 resolve 或者 rejected 傳入的值
  this.value = null

  // 用於保存 resolve 的回調函數
  this.resolvedCallbacks = []

  // 用於保存 reject 的回調函數
  this.rejectedCallbacks = []

  // 狀態轉變爲 resolved 方法
  function resolve(value) {
    // 判斷傳入元素是否爲 Promise 值,若是是,則狀態改變必須等待前一個狀態改變後再進行改變
    if (value instanceof MyPromise) {
      return value.then(resolve, reject)
    }

    // 保證代碼的執行順序爲本輪事件循環的末尾
    setTimeout(() => {
      // 只有狀態爲 pending 時才能轉變,
      if (self.state === PENDING) {
        // 修改狀態
        self.state = RESOLVED

        // 設置傳入的值
        self.value = value

        // 執行回調函數
        self.resolvedCallbacks.forEach((callback) => {
          callback(value)
        })
      }
    }, 0)
  }

  // 狀態轉變爲 rejected 方法
  function reject(value) {
    // 保證代碼的執行順序爲本輪事件循環的末尾
    setTimeout(() => {
      // 只有狀態爲 pending 時才能轉變
      if (self.state === PENDING) {
        // 修改狀態
        self.state = REJECTED

        // 設置傳入的值
        self.value = value

        // 執行回調函數
        self.rejectedCallbacks.forEach((callback) => {
          callback(value)
        })
      }
    }, 0)
  }

  // 將兩個方法傳入函數執行
  try {
    fn(resolve, reject)
  } catch (e) {
    // 遇到錯誤時,捕獲錯誤,執行 reject 函數
    reject(e)
  }
}

MyPromise.prototype.then = function (onResolved, onRejected) {
  // 首先判斷兩個參數是否爲函數類型,由於這兩個參數是可選參數
  onResolved =
    typeof onResolved === 'function'
      ? onResolved
      : function (value) {
          return value
        }

  onRejected =
    typeof onRejected === 'function'
      ? onRejected
      : function (error) {
          throw error
        }

  // 若是是等待狀態,則將函數加入對應列表中
  if (this.state === PENDING) {
    this.resolvedCallbacks.push(onResolved)
    this.rejectedCallbacks.push(onRejected)
  }

  // 若是狀態已經凝固,則直接執行對應狀態的函數

  if (this.state === RESOLVED) {
    onResolved(this.value)
  }

  if (this.state === REJECTED) {
    onRejected(this.value)
  }
}

手寫Promise.all()

Promise.all = function(iterator) {
  if (!Array.isArray(iterator)) return;
  let count = 0;
  let res = [];
  return new Promise((resolve, reject) => {
    for(let item of iterator) {
      Promise.resolve(item)
      .then(data => {
        res[count++] = data;
        if (count === iterator.length) {
          resolve(res);
        }
      })
      .catch(e => {
        reject(e);
      })
    }
  })
}

// test
let p1 = Promise.resolve(3);
let p2 = 4;
let p3 = new Promise(resolve => {
  setTimeout(resolve, 100, 'lee')
  // setTimeout的第三個日後參數都是用來做爲第一個參數也就是函數的參數,也就是實際上是setTimeout(resolve('lee'), 100)
});
Promise.all([p1, p2, p3]).then(data => {
  console.log(data);
})

手寫Promise.race()

Promise.race = function(iterator) {
  return new Promise((resolve, reject) => {
    for(let item of iterator) {
      Promise.resolve(item)
      .then(data => {
        resolve(data)
      })
      .catch(e => {
        reject(e)
      })
    }
  })
}

let p1 = new Promise(resolve => {
  setTimeout(resolve, 105, 'p1 done')
})
let p2 = new Promise(resolve => {
  setTimeout(resolve, 100, 'p2 done')
})
Promise.race([p1, p2]).then(data => {
  console.log(data); // p2 done
})
相關文章
相關標籤/搜索