Promise規範以及手寫Promise

進階的巨人001發表於2020-11-04

1.Promise的規範

在這裡插入圖片描述
用這個規範來舉一個例子:

var promise1 = new Promise((resolve,reject)=>{reject()})

promise1 
.then(null,function(){
  return 123 
})
.then(null,null)  
.then(
  ()=>{
    console.log('promise2 已完成')
  },
 ()=>{
    console.log('promise2 已拒絕')

第一眼看結果會返回什麼呢??

1.首先promise1返回一個已拒絕狀態,然後會進入.then的回撥,只要這個地方不throw err,都會進入promise的onfulfilled,記住這個已完成狀態和promise1沒關係了

2.根據我上面提到的規範,只要onFulffilled或者onRejected返回一個值X,就會進入onFulffilled狀態,所以123成功返回

3.到.then(null.null)這一步之後,再看第三條規則,onFulffilled不是函式並且狀態是已完成,必須成功執行並返回相同的值,所以123再次成功返回

4.所以最後會列印結果’promise2 已完成’

5.123也可以獲取到

 .then(
	 (value)=>{
     console.log('promise2 已完成',value)   //value為123
 },

2.手寫Promise

class Promise{
  constructor(handleFunction){
      this.status = 'pending'
      this.value = undefined
      this.fulfilledList = []
      this.rejectedList = []
      
      handleFunction(this.triggerResolve.bind(this),this.triggerReject.bind(this))
  }

  triggerResolve(val){
      //當前的promise狀態已經變成了resolve,要執行後續的操作
      setTimeout(()=>{
        if(this.status !== 'pending') return

        if(val instanceof Promise){
           val.then(
             value => {},
             err => {}
           )
        }else{
          //resolve方法傳入的是普通值
          this.status = 'fulfilled'
          this.value = val
          this.triggerFulfilled(val)
        }
      },0)
  }

  triggerFulfilled(val){
     this.fulfilledList.forEach(item =>item(val))
     this.fulfilledList = []
  }

  triggerReject(){
      
  }

  then(onFulfilled,onRejected){
    const { value , status } =  this;
    return new Promise((onNextFulfilled,onNextRejected)=>{
      function onFinalFulfilled(val){
        if(typeof onFulfilled !== 'function'){
          onNextFulfilled(val)
        }else{
          const res = onFulfilled(val)
          if(res instanceof Promise){
            res.then(onNextFulfilled,onNextRejected)
          }else{
            onNextFulfilled(res)
          }
        }
      }
      function onFinalRejected(error){
        if(typeof onRejected !== 'function'){
          onNextRejected(error)
        }else{
          let res = null
          try{
            res = onRejected(error)
          } catch(e){
            onNextRejected(e)
          }
          if(res instanceof Promise){
            res.then(onNextFulfilled,onNextRejected)
          }else{
            onFulfilled(res)
          }
        }
      }
        switch(status){
          case 'pending':{
            this.fulfilledList.push(onFinalFulfilled)
            this.rejectedList.push(onFinalRejected)
            break;
          }
          case 'fulfilled':{
            onFinalFulfilled(value)
            break;
          }
        }
    })
  }
  catch(onRejected){
    return this.then(null,onRejected)
  }

  static resolve(value){
     if(value instanceof Promise)  return value
     return new Promise(resolve => resolve(value))
  }

  static reject(){

  }

  static all(list){
     return new Promise((resolve,reject)=>{
       let count = 0 ;
       const values = []
       for(const [i,promiseInstance] of list.entries()){
         Promise.resolve(promiseInstance)
         .then(res=>{
           values[i] = res;
           count++
           if(count === list.length){
             resolve(values)
           }
         },err =>{
           reject(err)
         })
       }
     })
  }

  static race(list){
     return  new Promise((resolve,reject)=>{
       list.forEach(item=>{
         Promise.resolve(item).then(res=>{
           resolve(res)
         },err =>{
           reject(err)
         })
       })
     })
  }
}

如何使用呢?

首先最簡單的用法就是

const promise = new Promise(function(resolve,reject){
  resolve('lsh')
})

多個then呼叫

const promise = new Promise(function(resolve,reject){
  resolve('lsh')
})
promise
.then(function(str){console.log(str); return str })
.then(function(str2){console.log('resolve2',str2)})

all呼叫

const promise = function(time){
  return new Promise(function(resolve,reject){
    return setTimeout(resolve,time)
  })
}

Promise.all([promise(1000),promise(2000)])
.then(function(){
  console.log('all promise resolved')
})

then延時呼叫

const promiseInstance = promise(0)
setTimeout(function(){
  promiseInstance.then(function(){console.log('你好啊');})
},3000)

其他功能暫未開發…

相關文章