手写promise

手写promise的过程是按照promise A+标准,先写测试用例,然后测试驱动开发,开发一个满足测试用例的promise。

class Promise2 {
  state = "pending";
  callbacks = [];
  resolve(result) {
    if (this.state !== 'pending') return
    this.state = 'fulfilled'
    nextTick(() => {
      this.callbacks.forEach((handle) => {
        if (typeof handle[0] === 'function') {
          handle[0].call(undefined,result)
        } 
      })
    })
  }
  reject(reason) {
    if (this.state !== 'pending') return
    this.state = 'rejected'
    nextTick(() => {
      this.callbacks.forEach((handle) => {
        if (typeof handle[1] === 'function') {
          handle[1].call(undefined,reason)
        } 
      })
    })
  }
  constructor(fn) {
    if(typeof fn != 'function'){
      throw new Error('Promise必须传入一个函数类型的参数')
    }
    fn(this.resolve.bind(this),this.reject.bind(this))
  }
  then(succeed?, fail?) {
    const handle = []
    if (typeof succeed === 'function') {
      handle[0] = succeed
    }
    if (typeof fail === 'function') {
      handle[1] = fail
    }
    this.callbacks.push(handle)
 
  }
}

export default Promise2;

function nextTick(fn) {
  if (process !== undefined && typeof process.nextTick === "function") {
    return process.nextTick(fn);
  } else {
    var counter = 1;
    var observer = new MutationObserver(fn);
    var textNode = document.createTextNode(String(counter));

    observer.observe(textNode, {
      characterData: true
    });

    counter = counter + 1;
    textNode.data = String(counter);
  }
}

总结:

1.promise有且只有三个状态:pending、fulfilled、rejected,状态之间的转换是只允许pending转向fulfilled或rejected,其它任何状态都不能相互转换。

2.封装的nextTick函数是用来兼容node环境和浏览器环境的,如果是node环境会直接使用process.nextTick;如果是浏览器环境,使用MutationObserver API来实现。(MutationObserver 接口提供了监视对 DOM 树所做更改的能力)

3.注意在写调用函数时,多想想函数的this是什么,是否符合我们预期的this,如果不符合,就需要使用bind或call方法指定函数的this。

下面是一个MutationObserver例子


111

你可能感兴趣的:(前端)