自己动手写 Promise | 全网最清晰简洁

// 手写 Promise,深入理解 node.js 事件循环与异步机制
class SPromise {
  static STATUS_PENDING = -1
  static STATUS_RESOLVED = 0
  static STATUS_REJECTED = 1

  constructor(callback) {
    if (typeof callback !== 'function') {
      throw new TypeError('Promise resolver is not a function')
    }
    // 定义 Promise 当前状态
    this.status = SPromise.STATUS_PENDING
    // 定义 Promise 值
    this.value = null
    // 定义 resolve/reject 时的承诺兑现回调
    this.onFulfill = [[], []]
    // Promise 创建即运行
    callback(this._genFulfiller(SPromise.STATUS_RESOLVED),
      this._genFulfiller(SPromise.STATUS_REJECTED)) 
  }

  then(onResolve, onReject) {
    return new SPromise((resolve, reject) => {
      function genCallback(fullfil, onFulfill) {
        return value => {
          if (typeof onFulfill === 'function') {
            let result = onFulfill(value)
            if (result instanceof SPromise) {
              // 若当前兑现回调仍返回 promise,则将它的兑现结果用来兑现当前 promise,由此可形成串联有序的 then 异步链
              result.then(resolve, reject)
            } else {
              fullfil(result)
            }
          } else {
            fullfil(value) // 当前 then 中无处理函数,直接将值传给下个 Promise 的 then
          }
        }
      }
      this.onFulfill[SPromise.STATUS_RESOLVED].push(genCallback(resolve, onResolve))
      this.onFulfill[SPromise.STATUS_REJECTED].push(genCallback(reject, onReject))
    })
  }

  _genFulfiller(status) {
    return value => {
      process.nextTick(() => { // 可以用 setImmediate,process.nextTick,setTimeout 等实验
        if (this.status !== SPromise.STATUS_PENDING) {
          return
        }
        this.status = status
        this.value = value
        let handler
        while (handler = this.onFulfill[status].shift()) {
          handler(this.value)
        }
      })
    }
  }
}

测试:

function test1() {
  let text = '界世,好你'
  return new SPromise((resolve, reject) => {
    setTimeout(() => {
      resolve(text.split(''))
    },1000)
  }).then((value) => { // 异步回调
    console.log('[then1]', value)
    return new SPromise((resolve, reject) => {
      setTimeout(() => {
        resolve(value.reverse())
      })
    })
  }).then((value) => { // 同步回调
    console.log('[then2]', value)
    return value.join('')
  }).then((value) => {
    console.log('[then3]', value)
  })
}

function test2() {
  const https = require('https')
  function get(keyword) {
    return new SPromise((resolve, reject) => {
      https.get('https://suggest.taobao.com/sug?code=utf-8&q=' + keyword, response => {
        let data = ''
        response.on('data', chunk => {
          data += chunk
        });
        response.on('end', () => {
          resolve(data)
        });
      }).on('error', err => {
        reject(err.message)
      })
    })
  }

  get('华为')
  .then((value) => { // 异步回调
    console.log('[then1]', value)
    return get('苹果')
  }).then((value) => { // 同步回调
    console.log('[then2]', value)
    return JSON.parse(value)
  }).then((value) => {
    console.log('[then3]', value['result'])
  })
}

test1()
.then(() => {
  console.log('---------------------------')
  test2()
})

输出:

[then1] [ '界', '世', ',', '好', '你' ]
[then2] [ '你', '好', ',', '世', '界' ]
[then3] 你好,世界
---------------------------
[then1] 
{"result":[["华为手机","92286.56965703903"],["华为手表","27807.92949657869"],["华为平板","22296.07215536921"],["华为手机壳","408213.7418392727"],[" 华为耳机","127327.02135785471"],["华为mate40pro 手机壳","93927.45274956428"],["华为p40pro手机壳","82318.16788240494"],["华为p50pro手机壳","48962.31444975183"],["华为蓝牙耳机","129108.50988561928"],["华为p30手机壳","73065.21080485791"]],"shop":"华为"}
[then2] 
{"result":[["苹果13","283281.39529907546"],["苹果13手机壳","324043.6103134092"],["苹果手机壳","560190.7401519603"],["苹果手机","558248.7950667278"],["苹果12手机壳","357129.2587940854"],["苹果11手机壳","342352.2528573405"],["苹果耳机","143633.09875067897"],["苹果12","407013.10131413804"],["苹果数据线","664766.3167561188"],["苹果13promax手机壳","294009.9901284209"]],"shop":"苹果"}
[then3] [
  [ '苹果13', '283281.39529907546' ],
  [ '苹果13手机壳', '324043.6103134092' ],
  [ '苹果手机壳', '560190.7401519603' ],
  [ '苹果手机', '558248.7950667278' ],
  [ '苹果12手机壳', '357129.2587940854' ],
  [ '苹果11手机壳', '342352.2528573405' ],
  [ '苹果耳机', '143633.09875067897' ],
  [ '苹果12', '407013.10131413804' ],
  [ '苹果数据线', '664766.3167561188' ],
  [ '苹果13promax手机壳', '294009.9901284209' ]
]

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值