当前位置:   article > 正文

面试题系列 手写Promise_手写promise面试题

手写promise面试题

目录

构建MyPromise基础类

实现Promise的then方法

MyPromise.resolve() 

MyPromise.reject() 

MyPromise.all()

MyPromise.race() 

MyPromise.any()

 MyPromise.allSettled()


构建MyPromise基础类

首先需要构建一个MyPromise类

  1. class MyPromise {
  2. constructor(executor) {
  3. this.initBind()
  4. this.initValue()
  5. try {
  6. executor(this.resolve, this.reject);
  7. } catch (e) {
  8. this.reject(e)
  9. }
  10. }
  11. initValue() {
  12. this.PromiseState = "pending"
  13. this.PromiseResult = null;
  14. this.onFulfilledCallbacks = []; // 保存成功的回调
  15. this.onRejectedCallbacks = []; // 保存失败的回调
  16. }
  17. initBind() {
  18. this.resolve = this.resolve.bind(this)
  19. this.reject = this.reject.bind(this)
  20. }
  21. resolve(value) {
  22. if(this.PromiseState !=="pending") return
  23. this.PromiseResult = value;
  24. this.PromiseState = "fulfilled"
  25. while(this.onFulfilledCallbacks.length) {
  26. let resolveFun = this.onFulfilledCallbacks.shift();
  27. resolveFun(this.PromiseResult)
  28. }
  29. }
  30. reject(reason) {
  31. if(this.PromiseState !=="pending") return
  32. this.PromiseResult = reason;
  33. this.PromiseState = "rejected"
  34. while(this.onRejectedCallbacks.length) {
  35. let rejectFun = this.onRejectedCallbacks.shift();
  36. rejectFun(this.PromiseResult)
  37. }
  38. }
  39. }

实现Promise的then方法

这个方法接受两个函数类型的参数,分别是成功和失败的回调函数

  1. MyPromise.prototype.then = function(onFulfilled, onRejected) {
  2. let state = this.PromiseState;
  3. // 首先校验这两个参数是不是一个函数
  4. onFulfilled = typeof onFulfilled === "function" ? onFulfilled : val => val
  5. onRejected = typeof onRejected === "function" ? onRejected : reason => { throw reason }
  6. if(state === "fulfilled") {
  7. // 执行成功的回掉函数
  8. // onFulfilled(this.PromiseResult)
  9. resolvePromise(onFulfilled)
  10. } else if(state==="rejected")
  11. // onRejected(this.PromiseResult)
  12. resolvePromise(onRejected)
  13. } else if(state ==="pending") {
  14. console.warn("遇到了异步函数,此时的状态肯定是pending,那么就把这个异步处理函数放到成功或者失败回调函数中,等到reject()或者resolve()的时候,再去调用");
  15. // console.log(onFulfilled, onRejected);
  16. this.onFulfilledCallbacks.push(resolvePromise.bind(this, onFulfilled))
  17. this.onRejectedCallbacks.push(resolvePromise.bind(this, onRejected))
  18. }
  19. })
  20. }

因为then方法是支持链式调用的,所以then方法的返回值也需要是一个MyPromise实例对象,所以我们在上面基础上做一定的修改

  1. MyPromise.prototype.then = function(onFulfilled, onRejected) {
  2. let state = this.PromiseState;
  3. // 首先校验这两个参数是不是一个函数
  4. onFulfilled = typeof onFulfilled === "function" ? onFulfilled : val => val
  5. onRejected = typeof onRejected === "function" ? onRejected : reason => { throw reason }
  6. var thenPromise = new MyPromise((resolve, reject) => {
  7. const resolvePromise = cb => {
  8. setTimeout(() => {
  9. try {
  10. const x = cb(this.PromiseResult)
  11. if (x === thenPromise) {
  12. // 不能返回自身哦
  13. throw new Error('不能返回自身。。。')
  14. }
  15. if (x instanceof MyPromise) {
  16. // 如果返回值是Promise
  17. // 如果返回值是promise对象,返回值为成功,新promise就是成功
  18. // 如果返回值是promise对象,返回值为失败,新promise就是失败
  19. // 谁知道返回的promise是失败成功?只有then知道
  20. x.then(resolve, reject)
  21. } else {
  22. // 非Promise就直接成功
  23. resolve(x)
  24. }
  25. } catch (err) {
  26. // 处理报错
  27. reject(err)
  28. throw new Error(err)
  29. }
  30. })
  31. }
  32. if(state === "fulfilled") {
  33. // 执行成功的回掉函数
  34. // onFulfilled(this.PromiseResult)
  35. resolvePromise(onFulfilled)
  36. } else if(state==="rejected"){
  37. // onRejected(this.PromiseResult)
  38. resolvePromise(onRejected)
  39. } else if(state ==="pending") {
  40. console.warn("遇到了异步函数,此时的状态肯定是pending,那么就把这个异步处理函数放到成功或者失败回调函数中,等到reject()或者resolve()的时候,再去调用");
  41. // console.log(onFulfilled, onRejected);
  42. this.onFulfilledCallbacks.push(resolvePromise.bind(this, onFulfilled))
  43. this.onRejectedCallbacks.push(resolvePromise.bind(this, onRejected))
  44. }
  45. })
  46. return thenPromise
  47. }

MyPromise.resolve() 

快速创建一个成功的MyPromise对象

  1. MyPromise.__proto__.resolve = function(value) {
  2. return new MyPromise((resolve, reject)=> {
  3. resolve(value)
  4. })
  5. }

MyPromise.reject() 

快速创建一个失败的MyPromsie对象

  1. MyPromise.__proto__.reject = function(reason) {
  2. return new MyPromise((resolve, reject)=> {
  3. reject(reason)
  4. })
  5. }

MyPromise.all()

这个函数接受一个数组类型的参数,该数组的每一项都是一个Promise,或者非Promise的对象。

如果每一项的Promise的状态结果都是fulfilled,也就是成功的,那么这个函数的返回结果就是所有Promise的执行结果列表,状态为fulfilled,并且和传入数组顺序一致

如果有至少一个Promise的状态是rejected,那么这个函数的返回结束就是这个失败的Promise的结果,并且状态为rejected

  1. MyPromise.__proto__.all = function(arr) {
  2. if(!Array.isArray(arr)) throw new Error("必须传入一个属猪")
  3. let resultArr = []
  4. let count = 0;
  5. return new MyPromise((resolve, reject)=>{
  6. for(let i = 0;i< arr.length; i++) {
  7. if(arr[i] instanceof MyPromise) {
  8. arr[i].then(res=>{
  9. // 这里不能使用push添加,顺序会错乱
  10. resultArr[i] = res;
  11. count++;
  12. if(count === arr.length) return resolve(resultArr)
  13. },err=>{
  14. return reject(err)
  15. })
  16. } else {
  17. resultArr[i] = arr[i]
  18. }
  19. }
  20. })
  21. }

MyPromise.race() 

接收一个数组类型的参数,返回结果是最先执行完的一个Promise,无论这个Promise事是成功还是失败的Promise 

  1. MyPromise.__proto__.race = function(arr) {
  2. if(!Array.isArray(arr)) throw new Error("传入参数必须是一个数组")
  3. return new MyPromise((resolve, reject)=>{
  4. arr.forEach((promise)=>{
  5. if(promise instanceof MyPromise) {
  6. promise.then(res=>{
  7. return resolve(res)
  8. }, err=>{
  9. return reject(err)
  10. })
  11. } else {
  12. return resolve(promise)
  13. }
  14. })
  15. })
  16. }

MyPromise.any()

该函数接受一个数组类型参数

1、如果参数中有一个Promise的状态是resolve,Promise.any() 返回一个resolve状态的Promise;
2、如果参数中全部的Promise的状态都变成了reject, Promise.any() 返回一个 reject 状态的Promise;

3、如果传递了一个空的数组,那么返回一个reject状态的Promise

  1. MyPromise.__proto__.any = function(arr) {
  2. if(!Array.isArray(arr)) throw new Error("传入参数必须是一个数组")
  3. let count = 0;
  4. return new MyPromise((resolve, reject)=>{
  5. arr.forEach((promise, index)=>{
  6. if(promise instanceof MyPromise) {
  7. promise.then(res=>{
  8. resolve(res)
  9. }, err=>{
  10. count++;
  11. if(count == arr.length) throw new Error("AggregateError: All MyPromises were rejected")
  12. })
  13. } else {
  14. resolve(promise)
  15. }
  16. })
  17. })
  18. }

 MyPromise.allSettled()

该函数接收一个数组类型的参数

返回所有Promise的处理结果 如果不是一个Promise,那么返回成功的Promise

value是成功的Promise返回结果 reason是失败的返回结果

[

{state: "rejected", reason: "***"},

{state: "fulfilled", value: "***"},

]

  1. MyPromise.__proto__.allSettled = function(arr) {
  2. if(!Array.isArray(arr)) throw new Error("传入参数必须是一个数组")
  3. return new MyPromise((resolve, reject)=>{
  4. let resultArr = []
  5. // let count = 0;
  6. for(let i = 0;i< arr.length;i++) {
  7. if(arr[i] instanceof MyPromise) {
  8. let obj = {status: "fulfilled"}
  9. arr[i].then(res=>{
  10. obj.value = res;
  11. },err=>{
  12. obj.status = "rejected"
  13. obj.reason = err;
  14. })
  15. resultArr[i] = obj
  16. } else {
  17. resultArr[i] = {
  18. status: "fulfilled",
  19. value: arr[i]
  20. }
  21. }
  22. }
  23. resolve(resultArr)
  24. })
  25. }
声明:本文内容由网友自发贡献,不代表【wpsshop博客】立场,版权归原作者所有,本站不承担相应法律责任。如您发现有侵权的内容,请联系我们。转载请注明出处:https://www.wpsshop.cn/w/寸_铁/article/detail/876556
推荐阅读
相关标签
  

闽ICP备14008679号