基础用法:

    1. let p = new Promise((resolve, reject) => {
    2. resolve('success')
    3. })
    4. console.log(p);
    5. p.then(value => {
    6. console.log(value);
    7. })
    • promse是一个类
    • 接收一个函数executor,而且这个它会立即执行
    • executor内部调用resolve(value)reject(reason)会把值传递到then方法(为啥这里叫方法不叫函数呢?)的回调里面,他们一定共享了value和reason在一个地方,是绑到全局还是this上呢
    • 要是在全局的话,多次new Promise呢?
    1. class Promise {
    2. constructor(executor) {
    3. this.value = undefined
    4. this.reason = undefined
    5. executor(this.resolve.bind(this), this.reject.bind(this))
    6. }
    7. resolve(value) {
    8. this.value = value
    9. }
    10. reject(reason) {
    11. this.reason = reason
    12. }
    13. then(onFulfilled, onRejected) {
    14. onFulfilled(this.value)
    15. // or
    16. onRejected(this.reason)
    17. }
    18. }
    19. module.exports = Promise
    • onFulfilledonRejected到底执行哪个,是不是需要给个标识呢
    • 这个标识存在哪里,在哪里变化呢,
    1. const Promise = require('./promise');
    2. let p = new Promise((resolve, reject) => {
    3. resolve('success')
    4. reject('error')
    5. })
    6. console.log(p);
    7. p.then(value => {
    8. console.log(value);
    9. }, reason => {
    10. console.log(reason);
    11. })
    • 根据promiseA+规范
    • 标识只能由PENGDING->FULFILLEDPENGDING->REJECTED,需加flag
    • excutor错误需要触发reject ```javascript const PENDING = ‘PENDING’ const FULFILLED = ‘FULFILLED’ const REJECTED = ‘REJECTED’ class Promise { constructor(executor) { this.status = PENDING this.value = undefined this.reason = undefined try {

      1. executor(this.resolve.bind(this), this.reject.bind(this))

      } catch (error) {

      this.reject.bind(this, error)
      

      } }

      resolve(value) { if (this.status === PENDING) {

      this.status = FULFILLED
      this.value = value
      

      } }

      reject(reason) { if (this.status === PENDING) {

      this.status = REJECTED
      this.reason = reason
      

      } }

      then(onFulfilled, onRejected) { if (this.status === FULFILLED) {

      onFulfilled(this.value)
      

      } if (this.status === REJECTED) {

      onRejected(this.reason)
      

      } }

    }

    module.exports = Promise

    回调:
    
    - 到目前为止,像点样子了,
    - 把耗时的工作放到了executor里面,then里面注册回调,当耗时的工作(目前只支持同步的,为啥)做完了,会调用then,同时执行then里面注册的回调(这里的回调只是在then里面,**excutor里拿不到**),所以必须excutor执行完了再执行then,不然回调就丢了。
    - 🌚,这就导致了它现在还不支持异步
    ```javascript
    const Promise = require('./promise');
    
    let p = new Promise((resolve, reject) => {
        setTimeout(() => {
            resolve('success')
        }, 1000)
    })
    
    console.log(p);
    
    p.then(value => {
        console.log(value);
    }, reason => {
        console.log(reason);
    })
    // Promise { status: 'PENDING', value: undefined, reason: undefined }
    
    • 那么要想让他支持异步怎么办呢?
    • 在excutor异步回调里,再去执行我们在then里注册的回调,这就需要这个回调能访问到,很容易我就可以想到:把它也放到this上呀。
    • 从上面我们可以看到,then里的两个回调都没执行,理由是,这是状态还在PENDING;
    • 所以这种状态下,我们需要把回调存起来 ```javascript const PENDING = ‘PENDING’ const FULFILLED = ‘FULFILLED’ const REJECTED = ‘REJECTED’ class Promise { constructor(executor) { this.status = PENDING this.value = undefined this.reason = undefined this.onFulfilledCb = null this.onRejectedCb = null try {

      executor(this.resolve.bind(this), this.reject.bind(this))
      

      } catch (error) {

      this.reject.bind(this, error)
      

      } }

      resolve(value) { if (this.status === PENDING) {

      this.status = FULFILLED
      this.value = value
      this.onFulfilledCb(this.value)
      

      } }

      reject(reason) { if (this.status === PENDING) {

      this.status = REJECTED
      this.reason = reason
      this.onRejectedCb(this.reason)
      

      } }

      then(onFulfilled, onRejected) { if (this.status === FULFILLED) {

      onFulfilled(this.value)
      

      } if (this.status === REJECTED) {

      onRejected(this.reason)
      

      } if (this.status === PENDING) {

      this.onFulfilledCb = onFulfilled
      this.onRejectedCb = onRejected
      

      } }

    }

    module.exports = Promise

    ok,先看起来是不是完美了?<br />其实,promise还有很多骚操作呢。<br />比如下方:
    ```javascript
    const Promise = require('./promise');
    
    let p = new Promise((resolve, reject) => {
        setTimeout(() => {
            resolve('success')
        }, 1000)
    })
    
    console.log(p);
    
    p.then(value => {
        console.log(value);
    }, reason => {
        console.log('sdf', reason);
    })
    // 多次在同一个promise上执行then方法呢?注意,这里不是链式调用
    p.then(value=>{
        console.log(value);
    })
    // 期望打印两次
    // 实际只打印了一次
    

    再一次改造:

    const PENDING = 'PENDING'
    const FULFILLED = 'FULFILLED'
    const REJECTED = 'REJECTED'
    class Promise {
      constructor(executor) {
        this.status = PENDING
        this.value = undefined
        this.reason = undefined
        this.onFulfilledCbs = []
        this.onRejectedCbs = []
        try {
          executor(this.resolve.bind(this), this.reject.bind(this))
        } catch (error) {
          this.reject.bind(this, error)
        }
      }
    
      resolve(value) {
        if (this.status === PENDING) {
          this.status = FULFILLED
          this.value = value
          this.onFulfilledCbs.forEach(fn=>fn(this.value))
        }
      }
    
      reject(reason) {
        if (this.status === PENDING) {
          this.status = REJECTED
          this.reason = reason
          this.onRejectedCbs.forEach(fn => fn(this.value))
        }
      }
    
      then(onFulfilled, onRejected) {
        if (this.status === FULFILLED) {
          onFulfilled(this.value)
        }
        if (this.status === REJECTED) {
          onRejected(this.reason)
        }
        if (this.status === PENDING) {
          this.onFulfilledCbs.push(()=>{
            // 在这里传值是不是很奇怪呀
            onFulfilled(this.value)
          }) 
          this.onRejectedCbs.push(()=>{
            onRejected(this.reason)
          })
        }
    
      }
    
    }
    
    module.exports = Promise
    

    改造后,达到我们的预期了。
    那么,接着来的链式调用呢:

    const Promise = require('./promise');
    
    let p = new Promise((resolve, reject) => {
        setTimeout(() => {
            resolve('success')
        }, 100)
    })
    
    p.then(value => {
        console.log(value);
        return 100
    }, reason => {
        console.log(reason);
    }).then(value => {
        console.log(value)
    })
    

    看起来又捉襟见肘了,如何支持链式调用呢?

    // 会不会如下呢,then里返回this
    
      then(onFulfilled, onRejected) {
        if (this.status === FULFILLED) {
          onFulfilled(this.value)
        }
        if (this.status === REJECTED) {
          onRejected(this.reason)
        }
        if (this.status === PENDING) {
          this.onFulfilledCbs.push((value)=>{
            onFulfilled(value)
          }) 
          this.onRejectedCbs.push((reason)=>{
            onRejected(reason)
          })
        }
        return this
      }
    

    确实不报错了, 但也不符合我们的预期,根据推测,第一次then之后应该,返回的是一个新的promise,我们暂且叫它promise2

    const PENDING = 'PENDING'
    const FULFILLED = 'FULFILLED'
    const REJECTED = 'REJECTED'
    class Promise {
      constructor(executor) {
        this.status = PENDING
        this.value = undefined
        this.reason = undefined
        this.onFulfilledCbs = []
        this.onRejectedCbs = []
        try {
          executor(this.resolve.bind(this), this.reject.bind(this))
        } catch (error) {
          this.reject.bind(this, error)
        }
      }
    
      resolve(value) {
        if (this.status === PENDING) {
          this.status = FULFILLED
          this.value = value
          this.onFulfilledCbs.forEach(fn => fn(this.value))
        }
      }
    
      reject(reason) {
        if (this.status === PENDING) {
          this.status = REJECTED
          this.reason = reason
          this.onRejectedCbs.forEach(fn => fn(this.value))
        }
      }
    
      then(onFulfilled, onRejected) {
        let promise2 = new Promise((resolve, reject) => {
    
          if (this.status === FULFILLED) {
            // repeat
            try {
              let x = onFulfilled(this.value)
              resolve(x)
            } catch (error) {
              reject(error)
            }
          }
          if (this.status === REJECTED) {
            // repeat
            try {
              let x = onRejected(this.reason)
              resolve(x)
            } catch (error) {
              reject(error)
            }
          }
          if (this.status === PENDING) {
            this.onFulfilledCbs.push((value) => {
              // 我们把值传递过来啦
              // repeat
              try {
                let x = onFulfilled(value)
                resolve(x)
              } catch (error) {
                reject(error)
              }
            })
            this.onRejectedCbs.push((reason) => {
              // repeat
              try {
                let x = onRejected(reason)
                resolve(x)
              } catch (error) {
                reject(error)
              }
            })
          }
        })
        return promise2
      }
    
    }
    
    module.exports = Promise
    

    这样确实实现了链式调用,我确实有一些疑问,为什么48行明明rejected了,却还要调resolve,将值流转的promise2的then的onFulfilled里面,为什么catch的error要调reject,将值流转到promise2的then的onRejected里面。
    这些其实是promiseA+规范里定的:除了抛错或promise,其他都是普通值,会流转到下一个then到onFulfilled里面。

    Wait,抛错和普通值我们知道了,promise是什么鬼?

    const Promise = require('./promise');
    
    function sleep(time) {
        return new Promise((resolve, reject) => {
            setTimeout(() => {
                resolve(time)
            }, time)
        })
    }
    
    let p = new Promise((resolve, reject) => {
        setTimeout(() => {
            resolve(100)
        }, 100)
    })
    
    p.then(value => {
        return sleep(value)
    }, reason => {
        console.log(reason);
    }).then(value => {
        console.log(value)
    })
    

    我们判断下return的x是什么值

    const PENDING = 'PENDING'
    const FULFILLED = 'FULFILLED'
    const REJECTED = 'REJECTED'
    const resovePromise = (x, promise2, resolve, reject) => {
      if (x === promise2) {
        return reject(new TypeError())
      }
      if ((typeof x === 'object' && x !== null) || typeof x === 'function') {
        try {
          let then = x.then
          // thenable
          if (typeof then === 'function') {
            then.call(x, (y) => {
              resolve(y)
            }, (r) => {
              reject(r)
            })
          } else {
            resolve(x)
          }
        } catch (error) {
          reject(error)
        }
      } else {
        resolve(x)
      }
    }
    class Promise {
      constructor(executor) {
        this.status = PENDING
        this.value = undefined
        this.reason = undefined
        this.onFulfilledCbs = []
        this.onRejectedCbs = []
        try {
          executor(this.resolve.bind(this), this.reject.bind(this))
        } catch (error) {
          this.reject.bind(this, error)
        }
      }
    
      resolve(value) {
        if (this.status === PENDING) {
          this.status = FULFILLED-
          this.value = value
          this.onFulfilledCbs.forEach(fn => fn(this.value))
        }
      }
    
      reject(reason) {
        if (this.status === PENDING) {
          this.status = REJECTED
          this.reason = reason
          this.onRejectedCbs.forEach(fn => fn(this.value))
        }
      }
    
      then(onFulfilled, onRejected) {
        let promise2 = new Promise((resolve, reject) => {
    
          if (this.status === FULFILLED) {
            setTimeout(() => {
              try {
                let x = onFulfilled(this.value)
                resovePromise(x, promise2, resolve, reject)
              } catch (error) {
                reject(error)
              }
            }, 0);
          }
          if (this.status === REJECTED) {
            setTimeout(() => {
              try {
                console.log(promise2);
                let x = onRejected(this.reason)
                resovePromise(x, promise2, resolve, reject)
              } catch (error) {
                reject(error)
              }
            }, 0);
          }
          if (this.status === PENDING) {
            this.onFulfilledCbs.push((value) => {
              // 我们把值传递过来啦
              setTimeout(() => {
                try {
                  let x = onFulfilled(value)
                  resovePromise(x, promise2, resolve, reject)
                } catch (error) {
                  reject(error)
                }
              }, 0);
            })
            this.onRejectedCbs.push((reason) => {
              setTimeout(() => {
                try {
                  let x = onRejected(reason)
                  resovePromise(x, promise2, resolve, reject)
                } catch (error) {
                  reject(error)
                }
              }, 0);
            })
          }
        })
        return promise2
      }
    
    }
    
    module.exports = Promise