es6面试题:手写promise

66 阅读3分钟

1.创建class类函数

2.执行class类函数,给函数传递回调函数(resolve,reject)=>{},constructor函数接收回调函数executor

3.定义resolve,reject函数

4.调用回调函数executor

4.设计promise状态:promise 有3种状态:pending进行中,fulfilled已完成,rejected已拒绝

5.状态发生改变时,状态不可逆

6.定义then方法,then接收两个函数,一个成功函数,一个失败函数.then函数可以继续链式调用then方法,所以then函数返回的是一个myPromise实例。

7.then函数不是立即执行而是需要等状态发生改变后(resolve(1)或者rejected('throw err')执行完后)再执行then函数,否则拿不到_value值.所以先将函数存起来。事件循环机制:等待消息队列中的resolve(1)执行成功后再调用微任务中的then方法。

8.循环调用保存在数组中的函数,在微任务中执行该函数。执行完后删除该函数。

  /**
   * 1.创建class类函数
   * 2.执行class类函数,给函数传递回调函数`(resolve,reject)=>{}`,constructor函数接收回调函数executor
   * 3.定义resolve,reject函数
   * 4.调用回调函数executor
   * 4.设计promise状态:promise 有3种状态:pending进行中,fulfilled已完成,rejected已拒绝
   * 5.状态发生改变时,状态不可逆
   * 6.定义then方法,then接收两个函数,一个成功函数,一个失败函数.then函数可以继续链式调用then方法,所以then函数返回的是一个myPromise实例。
   * 7.then函数不是立即执行而是需要等状态发生改变后(resolve(1)或者rejected('throw err')执行完后)再执行then函数,否则拿不到_value值.所以先将函数存起来。事件循环机制:等待消息队列中的resolve(1)执行成功后再调用微任务中的then方法。
   * 8.循环调用保存在数组中的函数,在微任务中执行该函数。执行完后删除该函数。
  */

  /**
   * 运行一个微队列任务
   * 把传递的函数放到微队列中
  */
 function runMicroTask(callback){
  //模拟微队列
  //在node环境中运行js代码,用判断process写微任务
  if(typeof process!=='undefined' && process.nextTick){
    process.nextTick(callback)
  }else if(MutationObserver){
    //在浏览器环境中运行js代码,用判断MutationObserver观察器写微任务
    const p=document.createElement('p')
    //观察器,元素变化了,就执行该函数
   const observer= new MutationObserver(callback)
    observer.observe(p,{
      childList:true
    })
    p.innerHTML='1'
  }else{
    setTimeout(callback,0)
  }

 }
 
 function isPromise(obj){ 
   return !!(obj&&typeof obj==='object'&&typeof obj.then==='function')
 }


 const PENDING='pending'
 const FULFILLED='fulfilled'
 const REJECTED='rejected'
 class myPromise{
  constructor(executor){
    this._state=PENDING
    this._value=null
    this._handles=[] //保存then函数方法,等待状态发生改变后再执行then函数方法
    try{
      executor(this._resolve.bind(this),this._reject.bind(this))
    }catch(err){
      this._reject(err)
    }
   
  }
  _changeState(state,value){
    if(this._state!==PENDING){
      return 
    }
    
    this._state=state
    this._value=value
   
   
  }
  /**
   * @param {Function} executor  添加函数
   * @param {String} state  该函数什么状态下执行
   * @param {Function} resolve  让then函数返回的Promise成功
   * @param {Function} reject  让then函数返回的Promise失败
   */
  _pushHandles(executor,state,resolve,reject){
    this._handles.push({
      executor,
      state,
      resolve,
      reject
    })
  }
  _runHandles(){
    if(this._state==PENDING){//状态在等待状态时,不执行队列
      return 
    }
    while (this._handles[0]) {
        const handle=this._handles[0]
        this._runOneHandle(handle)
        this._handles.shift();
      }
  }
  _runOneHandle({executor,state,resolve,reject}){
   
    runMicroTask(()=>{
      if(this._state!==state){//当前状态和队列状态不一致,不处理
        return 
      }
      if(typeof executor!=='function'){
        this._state===FULFILLED?resolve(this._value):reject(this._value)
        return 
      }
      try{
        let res=executor(this._value) //then函数返回值,判断返回值是不是promise
       
      if(isPromise(res)){
        res.then(resolve,reject)
      }else{
        resolve(res)
      }
      }catch(err){
        reject(err)
      }

      
    })
   
    
  }
  _resolve(data){//当状态发生改变时,状态不可逆。
    this._changeState(FULFILLED,data)
    this._runHandles()//状态变化,执行队列
  }
  _reject(err){//当状态发生改变时,状态不可逆。
    this._changeState(REJECTED,err)
    this._runHandles()//状态变化,执行队列
   
  }
  then(onFulfilled,onRejected){
   

    return new myPromise((resolve,reject)=>{
       //保存then方法。等待状态变化后再执行then方法
        this._pushHandles(onFulfilled,FULFILLED,resolve,reject)
        this._pushHandles(onRejected,REJECTED,resolve,reject)
        //执行队列
        this._runHandles()
    })
  }
 }

let pro=new myPromise((resolve,reject)=>{
  
  setTimeout(()=>{
   
    resolve(1) //状态发生改变
    resolve(2)//状态已发生改变,状态不可逆
    reject('trow err') //状态已发生改变,状态不可逆

  },100)
})
pro.then((res)=>{
  console.log('then--res===1',res)
   return '678'
},(err)=>{

}).then((res)=>{
  console.log('then--res===2',res)
  return new myPromise((resolve)=>{
    resolve('999')
  })
}).then((res)=>{
  console.log('then--res===4',res)
})
pro.then((res)=>{
  console.log('then--res===3',res)
})