手写一个函数实现简易版的promise(包括resolve,reject,then,catch,finally,all方法的实现)

本文介绍了如何从头开始实现一个简单的Promise类,包括状态管理、错误处理和then/catch方法,并通过实战用例展示了其在异步编程中的应用。此外,还探讨了myPromise.all的特性及其实现原理。
摘要由CSDN通过智能技术生成

手写promise的代码如下:

class myPromise {
    static PENDING = 'pending'
    static FULFILLED = 'fulfilled'
    static REJECTED = 'rejected'

    static resolve (value) {
        if (value && value.then) {
            return value
        }
        return new myPromise((resolve) => resolve(value))
    }

    static reject (value) {
        return new myPromise((_, reject) => reject(value))
    }

    constructor (fn) {
        this.status = myPromise.PENDING
        this.result = null

        this.resFns = []
        this.rejFns = []

        const resolve = (value) => {
            if (this.status === myPromise.PENDING) {
                setTimeout(() => {
                    this.status = myPromise.FULFILLED
                    this.result = value
                    this.resFns.forEach(({fn, resolve, reject}) => resolve(fn(value)))
                })
            }
        }

        const reject = (reason) => {
            if (this.status === myPromise.PENDING) {
                setTimeout(() => {
                    this.status = myPromise.REJECTED
                    this.result = reason
                    this.rejFns.forEach(({fn, resolve, reject}) => reject(fn(reason)))
                })
            }
        }

        try {
            fn(resolve, reject)
        } catch (err) {
            reject(err)
        }
    }

    then (resFn, rejFn) {
        resFn = typeof resFn === 'function' ? resFn : value => value
        rejFn = typeof rejFn === 'function' ? rejFn : reason => reason

        const _promise = {
            [myPromise.PENDING]: () => {
                return new myPromise((resolve, reject) => {
                    this.resFns.push({fn: resFn, resolve, reject})
                    this.rejFns.push({fn: rejFn, resolve, reject})
                })
            },
            [myPromise.FULFILLED]: () => myPromise.resolve(resFn(this.result)),
            [myPromise.REJECTED]: () => myPromise.reject(rejFn(this.result))
        }[this.status]

        return _promise()
    }

    catch (fn) {
        return this.then(undefined, fn)
    }

    finally(cb) {
        return this.then(cb, cb)
    }

    static all (iterable) {
        return new myPromise((resolve, reject) => {
            const arr = Array.from(iterable)
            const result = []
            let count = 0
            arr.forEach((item, i) => {
                myPromise.resolve(item).then(res => {
                    result[i] = res
                    count++
                    if (count === arr.length) {
                        resolve(result)
                    }
                }).catch(err => reject(err))
            })
        })
    }
}

// 用例1
// myPromise.resolve(10)
// .then(o => o * 10)
// .then(o => o + 10)
// .then(o => {
//     console.log(o)
// })

// 用例2
// new myPromise((resolve, reject) => reject('报错了'))
// .then(e => {
//     console.log('Error', e)
// })
// .catch(err => {
//   console.log(err)
// })

// 用例3
// myPromise.all([123, Promise.resolve('hahah'), Promise.resolve('lalal')])
// .then(res => {
//     console.log(res)
// })
// .catch(err => {
//     console.log(err)
// })

// 用例4
// let p1 = new myPromise((resolve, reject) => {
//     resolve(1)
// }).then((value) => {
//     console.log(value)
// }).catch((e) => {
//     console.log(e)
// }).finally(() => {
//     console.log('finally')
// })

//用例5
console.log(1);
const promise = new myPromise((resolve, reject) => {
  console.log(2);
    setTimeout(() => {
        resolve('success');
        console.log(4);
    }, 2000);
})
promise.then(value => {
    console.log(11)
    console.log('resolve', value)
    return value
}).then((value) => {
    console.log(22)
    console.log('resolve', value)
})
console.log(3);

promise.all的特点:接受一个由promise对象组成的多项数组,当数组中的每一项都返回fulfilled,则才算当前的状态变更为fulfilled;
只要有一个抛出错误,变更为rejected,当前的状态才变更为rejected。
而且当全部成功后,返回的回调参数是按原数组的顺序返回的

手动实现的代码如下:

function PromiseAll (proArry) {
  let result = []
  let count = 0
  return new Promise((resolve,reject) => {
    for(let i=0;i<proArry.length;i++) {
      Promise.resolve(proArry[i]).then(res => {
      // 这里不用push是因为,每一个promise对象返回的时间可能有长有短
      //为了按照原顺序输入,使用key的方式添加
      // 定义count变量,而不直接使用result.length进行比较,也是如此
        result[i] = res;
        count++;
        if(proArry.length === count) {
          resolve(result)
        }
      }).catch(err => {
      // 只要有一项抛出错误,就会调用new Promise的reject
        reject(err)
      })
    }
  })
}

js快排实现:

// 分区函数,负责把数组分按照基准值分为左右两部分
// 小于基准的在左侧,大于基准的在右侧最后返回基准值的新下标
function partition(arr, left, right) {
  // 基准值可以是left与right之间的任意值,再将基准值移动至最左或最右即可。
  // 直接基于中间位置排序,则需要基于中间位置左右交换,参加基于中间位置交换的版本。
  // var tmpIndex = Math.floor((right - left) / 2)
  // ;[arr[left + tmpIndex], arr[right]] = [arr[right], arr[left + tmpIndex]]

  var pivotIndex = right
  var pivot = arr[pivotIndex]
  var partitionIndex = left - 1
  for (var i = left; i < right; i++) {
    // 如果比较项小于基准值则进行交换,并且分区索引增加1位
    // 也就是将大于基准值的全部往右侧放,以分区索引为分割线
    if (arr[i] < pivot) {
      partitionIndex++
      if (partitionIndex !== i) {
        [arr[partitionIndex], arr[i]] = [arr[i], arr[partitionIndex]]
      }
    }
  }
  partitionIndex++;
  [arr[partitionIndex], arr[pivotIndex]] = [arr[pivotIndex], arr[partitionIndex]]
  return partitionIndex
}

// 分区递归版本,分区递归调用。
function quickSort2(arr, left, right) {
  left = left !== undefined ? left : 0
  right = right !== undefined ? right : arr.length - 1
  if (left < right) {
    var pivot = partition(arr, left, right)
    quickSort2(arr, left, pivot - 1)
    quickSort2(arr, pivot + 1, right)
  }
  return arr
}
  • 1
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值