手写 Promise 所有方法实现

作者 : 开心源码 本文共3250个字,预计阅读时间需要9分钟 发布时间: 2022-05-13 共232人阅读

前言

上次我们手写了一个promise,相信大家已经对 Promise 有了深度的了解,这次我们再把 Promise 的所有相关方法都实现一下。

Promise.prototype.catch

Promise.prototype.catch = function(onRejected) {  return this.then(null, onRejected)}

catch 方法相对简单,就是调用 promise 自身的 then 方法,只传入失败的回调。由于 then 方法本身具备值的传递性,所以我们只要传入失败的回调就可,即便没有成功的回调,也会将值自动的传递下去。

Promise.prototype.finally

无论成功还是失败都会执行 finally

Promise.prototype.finally = function(onFinished) {  return this.then(val => {    onFinished()    return val  }).catch((err) => {    onFinished()    return err  })}

finally 需要注意

  1. finally 的回调没有参数

  2. promise 假如成功,则将成功的值正常传递下去,不会因 finally 而断掉,举例:

  3. promise 假如失败,同上

Promise  .resolve(1)  .finally(val => console.log(val)) // undefind  .then(val => console.log(val)) // 1Promise  .reject('error')  .finally(val => console.log(val)) // undefind  .catch(err => console.log(err)) // error

Promise.resolve

返回一个成功的 promise

Promise.resolve = function(val) {  return new Promise(resolve => {    resolve(val)  })}

emmm 一眼就懂

image

Promise.reject

返回一个失败的 promise

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

啥也不说了。。。

image

Promise.all

返回一个 promise 实例。接受一个可迭代的对象,会等 iterable 参数内所有的 promise 都 resolved 时被 reslove,假如有一个 rejected,则此实例被 reject。

假如 iterable 没有 promise,则此实例直接被 resolve。

返回值是一个数组,数组的值按照 iterable 的迭代顺序排列。

Promise.all = function(ps) {  let resolve  let reject  const promise = new Promise((r, j) => {    resolve = r    reject = j  })  let fufilledCount = 0  let index = 0;  const ret = [];  const wrapFufilled = i => {    return val => {      fufilledCount += 1      ret[i] = val      if (fufilledCount >= index) {        resolve(ret)      }    }   }  const wrapRejected = i => {    return err => {      reject(err)    }  }  for (let p of ps) {    Promise.resolve(p).then(wrapFufilled(index), wrapRejected(index))    index += 1  }  return promise}

注意几个要点

  1. 由于接受的是一个可迭代对象(iterable),所以我们用 for of 遍历。

  2. 这里我们用 Promise.resolve() 包装一下所有的 promise。

  3. wrapFufilled 的目的是为了记录当前遍历的 index。

Promise.race

返回一个 promise,一旦迭代器中的某个promise处理或者拒绝,返回的 promise就会处理或者拒绝。

Promise.race = function(ps) {  let resolve  let reject  const promise = new Promise((r, j) => {    resolve = r    reject = j  })  for (let p of ps) {    Promise.resolve(p).then(      val => resolve(val),      err => reject(err)    )  }  return promise}

Promise.any

只需其中的一个 promise 成功,就返回那个已经成功的 promise 。假如可迭代对象中没有一个 promise 成功(即所有的 promises 都失败/拒绝),就返回一个失败的 promise 和AggregateError类型的实例,它是 Error 的一个子类,用于把单一的错误集合在一起。

本质上,这个方法和Promise.all()是相反的

Promise.any = function(ps) {  let resolve  let reject  const promise = new Promise((r, j) => {    resolve = r    reject = j  })  let errCount = 0  let pCount = 0  for (let p of ps) {    pCount += 1    Promise.resolve(p).then(      val => resolve(val),      err => {        errCount += 1        if (errCount >= pCount) {          reject(new AggregateError('All promises were rejected'))        }      }    )  }  return promise}

Promise.allSettled

返回一个在所有给定的promise都已经fulfilled或者rejected后的promise,并带有一个对象数组,每个对象表示对应的promise结果。

这里举一个例子:

const promise1 = Promise.resolve(3);const promise2 = new Promise((resolve, reject) => setTimeout(reject, 100, 'foo'));const promises = [promise1, promise2];Promise.allSettled(promises).  then((results) => results.forEach((result) => console.log(result)));// 输出结果// Object { status: "fulfilled", value: 3 }// Object { status: "rejected", reason: "foo" }

具体实现:

Promise.allSettled = function(ps) {  let resolve  let reject  const promise = new Promise((r, j) => {    resolve = r    reject = j  })  let finishedCount = 0  let index = 0;  const ret = [];  const wrapFufilled = i => {    return val => {      finishedCount += 1      ret[i] = {        status: 'fufilled',        value: val      }      if (finishedCount >= index) {        resolve(ret)      }    }   }  const wrapRejected = i => {    return err => {      finishedCount += 1      ret[i] = {        status: 'rejected',        value: err      }      if (finishedCount >= index) {        resolve(ret)      }    }  }  for (let p of ps) {    Promise.resolve(p).then(wrapFufilled(index), wrapRejected(index))    index += 1  }  return promise}
说明
1. 本站所有资源来源于用户上传和网络,如有侵权请邮件联系站长!
2. 分享目的仅供大家学习和交流,您必须在下载后24小时内删除!
3. 不得使用于非法商业用途,不得违反国家法律。否则后果自负!
4. 本站提供的源码、模板、插件等等其他资源,都不包含技术服务请大家谅解!
5. 如有链接无法下载、失效或广告,请联系管理员处理!
6. 本站资源售价只是摆设,本站源码仅提供给会员学习使用!
7. 如遇到加密压缩包,请使用360解压,如遇到无法解压的请联系管理员
开心源码网 » 手写 Promise 所有方法实现

发表回复