手写Promise相关方法

134 阅读1分钟

静态方法

Promise.resolve

Promise.resolve = function(data) {
  return new Promise((resolve, reject) => {
    resolve(data)
  })
}

Promise.all

Promise.all全部成功才会决议成功,否则失败

Promise.all = function(promises) {
  const result = [];
  let times = 0;//进行计数
  return new Promise((resolve, reject) => {
    function processResult(data, index) {
      result[index] = data;
      if(++times === promises.length) {
        resolve(result);
      }

    }
    for(let i = 0; i < promises.length; i++) {
      const promise = promises[i];
      //promise可能不是promise,因此需要再用Promise.resolve包装一下
      Promise.resolve(promise).then(data => {
        processResult(data, i);
      }, reject)
    }
  })
}

Promise.race

Promise.race取最先的结果为基准,不论是成功还是失败

Promise.race = function(promises) {
  return new Promise((resolve, reject) => {
    for(let i = 0; i < promises.length; i++) {
      const promise = promises[i];
      //promise可能不是promise,因此需要再用Promise.resolve包装一下
      Promise.resolve(promise).then(resolve, reject)
    }
  })
}

Promise.allSettled

用来确定一组异步操作是否都结束了(不管成功或失败),该方法返回的新的 Promise 实例,一旦发生状态变更,状态总是fulfilled,不会变成rejected

Promise.allSettled = function(promises) {
  let result = [];
  let times = 0;
  return new Promise((resolve, reject) => {
    function processResult(data, index, status) {
      if(status === 'fulfilled') {
        result[index] = {status, value: data};
      }else {
        result[index] = {status, reason: data};
      }
      if(++times === promises.length) {
        resolve(result);
      }
    }
    for(let i = 0; i < promises.length; i++) {
      const promise = promises[i];
      //promise可能不是promise,因此需要再用Promise.resolve包装一下
      Promise.resolve(promise).then(data => {
        processResult(data, i, 'fulfilled');
      }, err => {
        processResult(err, i, 'rejected');
      })
    }
  }) 
}

Promise.any

只要有一个成功,那就成功,全部失败,那就失败

Promise.any = function(promises) {

  const AggregateError = class extends Error{} 
  return new Promise((resolve, reject) => {
    let times = 0;
    function processResult() {
      if(++times === promises.length) {
        reject(new AggregateError('All promises were rejected'))
      }
    }
    for(let i = 0; i < promises.length; i++) {
      const promise = promises[i];
      //promise可能不是promise,因此需要再用Promise.resolve包装一下
      Promise.resolve(promise).then(resolve, err => {
        processResult();
      })
    }
  })
}

实例方法

Promise.prototype.finally

无论是否成功,都会执行

Promise.prototype.finally = function(callback) {
  
  return this.then(
    //callback可能返回promise,需要等待callback中返回的promise
    value => Promise.resolve(callback()).then(() => value), 
    err => Promise.resolve(callback()).then(() => {throw err}))
}

Promise.prototype.catch

捕获错误

Promise.prototype.catch = function(callback) {
  if(typeof callback !== 'function') {
    return;
  }

  return this.then(res => res, callback);
}

promisify

promisify用于将node中的异步回调API转为promise形式

function promisify(fn) {
  return function(...args) {
    return new Promise((resolve, reject) => {
      fn(...args, (err, data) => {
        if(err) return reject(err)
        resolve(data)
      })
    })
  }
}

用法:
const fs = require('fs');
const readFile = promisify(fs.readFile);
readFile('./test.txt', 'utf8').then(res => console.log(res))

promisifyAll:用于将一个对象上的多个方法转化为promise形式

function promisifyAll(obj) {
  let result = {};
  for(let key in obj) {
    //如果是函数再转化
    result[key] = typeof obj[key] === 'function' ? promisify(obj[key]) : obj[key]
  }

  return result;

}

//用法
const fs = require('fs');
const myFs = promisifyAll(fs);
myFs.readFile('./test.txt', 'utf8').then(res => console.log(res))