手写promise课程笔记(未完)

85 阅读3分钟

这个是尚硅谷promise课程中手写promise的笔记。

1. 基本结构

function Promise(executor){
    // 执行器函数会被立即同步调用
    exectutor()
}

Promise.prototype.then = function(onResovled, onRejected){

}

2. resolve和reject的结构

 function Promise(executor){
    // exectutor有两个函数参数
    exectutor(resolve, reject)
    
    // exectuor两个函数参数的定义
    function resolve(data){
    }
    
    function reject(data){
    }
}

Promise.prototype.then = function(onResovled, onRejected){

}

3.resolve/reject代码实现

resolve函数至少要做两件事: (1)改变promise的状态;(2)设置promise的结果。reject也是同样的


function Promise(executor){
   this.PromiseState = 'pending'
   this.PromiseResult = null
   
   const self = this
   funcion resolve(data){
      self.PromiseState = 'fulfilled'
      self.PromiseResult = data
       
      // 如果按照下面这样写,当调用resolve(xx)时,this实质是window对象。
      // this.PromiseState = 'fulfilled'
      // this.PromiseResult = data
   }
   
   function reject(data){
      self.PromiseState = 'rejected'
      self.PromiseResult = data
   }
   ...
}

此时可以测试一下新建一个promise,并进行reslove、reject的调用。

       function Promise(executer) {
            this.PromiseState = 'pending'
            this.PromiseResult = null

            const self = this

            executer(resolve, reject);

            function resolve(data) {
                self.PromiseState = 'fulfilled'
                self.PromiseResult = data
            }

            function reject(data) {
                self.PromiseState = 'rejected'
                self.PromiseResult = data
            }
        }

        const p = new Promise((resolve, reject) => {
            resolve(2)
        })
        console.log(p)

4. 通过throw改变promise状态

改变promise状态有三种方法,(1)resolve, (2)reject(3)throw an execption。 前面已经通过(1)(2)改变了promise状态,这里则实现(3)。

try{
  executer(resolve, reject)
}catch(e){
  self.PromiseState = 'rejected'
  self.PromiseResult = e
}

5.令promise状态只能改变一次

只需要在每次改变状态前先去check状态是否已经被改变即可。

if(selft.PromiseState !== 'pending') 
   return 

6. 实现then方法中执行callback

Promise.prototype.then = function(onResolved, onRejected) {
    if (this.PromiseState === 'fulfilled') {
        onResolved(this.PromiseResult)
    }
    if (this.PromiseState === 'rejected') {
        onRejected(this.PromiseResult)
     }
}

7 异步任务回调的执行

目前如果我们需要执行异步操作,then方法是无法执行的。例如:

let p = new Promise((resolve, reject) => {
   setTimeout(() => {
      resolve('ok')
   },1000)
})
// 现在是同步代码,当p执行then时,resolve还未执行,导致promise状态还是pending状态
// 而在前面的代码中,promise是pending状态时,then中的callback都是不会执行的。
p.then(res => console.log(res))

所以我们需要:

(1)在then中,需要判定是否是pending状态,如果是pending状态,我们需要有一些对应的处理。

Promise.prototype.then = function(onResolved, onRejected){
   ...
   if(this.PromiseState === 'pending') {
     // do something...
   }
}

(2)在resolve和reject函数中,我们需要调用then中的callback

resolve() {
   //call onResolved
}

reject() {
  // call onRejected
} 

为了使我们能够在resolve和reject函数中调用到then中的callback,我们需要把callback存储在对象上。

function Promise(executor){
  ....
  // 用来保存then中传的两个callback,帮助实现异步调用
  this. callback = {}
  
  function resolve(data){
     ....
     // 调用callback
     if(self.callback.onResolved){
        self.callback.onResolved(data)
     }
  }
  
  function reject(data){
     ... 
     // 调用callback
     if(self.callback.onRejected){
        self.callback.onRejected(data)
     }
  }
}

Promise.prototype.then = function(onResolved, onRejected){
   ...
   if(this.PromiseState === 'pending'){
      // 为callback赋值
      this.callback = {
         onResovled, 
         onRejected
      }
   }
}

8 指定多个回调的实现

目前当我们指定多个回调时,下面的会覆盖掉上面的。

p.then(res => {
       console.log(res)
   },
   err => {
       console.log(err)
   })
  
// 这里指定的回调会把上面指定的回调覆盖掉 
p.then(res => {
      alert(res)
   },
   err =>  {
      alert(err)
   })

所以我们需要修改保存回调的方式,让其能够保存多个回调,也就是说 需要把实例上存储的callback改为数组的形式

this.callback = []

在then中

if(this.PromiseState === 'pending'){
   this.callback.push({
       onResolved,
       onRejected
   })
}

当改变状态调用时

self.callback.forEach(cb => {
    cb.onResolved(data)
})

9 同步方式下then的返回结果实现

then的返回值应该是一个Promise. 在resolve时,如果返回的是非Promise,则返回的是Promise状态为fulfilled,PromiseResult根据resolve callback返回结果而定。

如果返回的是Promise,则状态和结果根据这个Promise而定。

Promise.prototype.then = function(onResvoled, onRejected){
    return new Promise((resolve, reject) => {
       if(this.PromiseState === 'fulfilled'){
          try{
             let result = onResolved(this.PromiseResult)
             // 这里的r和e是在使用时then中return的新Promise的resolve和reject的参数
             if(result instanceof Promise){
                result.then(r => resolve(r), e => reject(e))
             }else{
                resolve(result)
             }
          }catch(e){
            reject(e)
          }
       }
       .....
    })
}

10 .