Promise 方法的實現

求實亭下發表於2023-02-08

Promise finally

這是一個promise例項原型鏈上的方法

Promise.prototype.finally = function(func) {
  return this.then((value) => {
    Promise.resolve(func()).then(() => value)
  },
  (reason) => {
    Promise.resolve(func()).then(() => {throw reason})
  })
}

Promise.All

  if (!arr[Symbol.iterator]) throw 'param is not iterable';
  const promiseArr = Array.from(arr).map(a => {
    if (a instanceof Promise) {
      return a;
    } else {
      return Promise.resolve(a);
    }
  })
  if (promiseArr.length === 0) return Promise.resolve([]);
  return new Promise((resolve, reject) => {
    let result = [];
    let count = promiseArr.length;
    promiseArr.forEach((p, i) => {
      p.then((res => {
        result[i] = res;
        count--;
        if (count === 0) resolve(result);
      }, (reason) => reject(reason)))
    })
  })

注意點

  1. 入參必須是可迭代的
  2. 引數轉化為陣列,且所有的項必須轉化為Promise
  3. 返回值永遠是一個Promise
  4. 入參如果長度是0 那直接返回Promise.resolve([]) 不然Promise.all([])返回的promise永遠處於pending狀態

Promise.race

const PromiseRace = (arr) => {
  if (arr[Symbol.iterator] === undefined) return Promise.reject('param is not iterator')
  const promiseArr = Array.from(arr).map(a => {
    if (a instanceof Promise) {
      return a;
    } else {
      return Promise.resolve(a);
    }
  })
  return new Promise((resolve, reject) => {
    promiseArr.forEach((p, i) => {
      p.then((res => {
        resolve(res);
      }, (reason) => reject(reason)))
    })
  })
}

注意 Promise.race([])返回的應該是一個pending狀態的promise

Promise.any

const PromiseAny = (arr) => {
  if (arr[Symbol.iterator] === undefined) return Promise.reject('param is not iterator')
  const promiseArr = Array.from(arr).map(a => {
    if (a instanceof Promise) {
      return a;
    } else {
      return Promise.resolve(a);
    }
  })
  if (promiseArr.length === 0) return Promise.reject(new AggregateError([],'All promises were rejected'))
  return new Promise((resolve, reject) => {
    const errors = [];
    const count = promiseArr.length;
    promiseArr.forEach((p, i) => {
      p.then((res => {
        resolve(res);
      }, (reason) => {
        errors[i] = reason;
        count--;
        if (count === 0) {
          reject(new AggregateError(errors,'All promises were rejected'))
        }
      }))
    })
  })
}

注意

  1. Promise.any 返回的錯誤一定是AggregateError型別的

Promise.allSettled

const PromiseAllSettled = (arr) => {
  if (arr[Symbol.iterator] === undefined) return Promise.reject('param is not iterator')
  const promiseArr = Array.from(arr).map(a => {
    if (a instanceof Promise) {
      return a;
    } else {
      return Promise.resolve(a);
    }
  })
  if (promiseArr.length === 0) return Promise.resolve([])
  return new Promise((resolve, reject) => {
    const result = [];
    const count = promiseArr.length;
    promiseArr.forEach((p, i) => {
      p.then((res => {
        result[i] = {status: 'fulfilled', value: res};
        count--;
        if (count === 0) {
          resolve(result)
        }
      }, (reason) => {
        result[i] = {status: 'rejected', reason: reason};
        count--;
        if (count === 0) {
          resolve(result)
        }
      }))
    })
  })
}

返回內容的格式一定是{status: 'fulfilled', value: res}或者{status: 'rejected', reason: reason}

相關文章