Git Product home page Git Product logo

Comments (1)

zhanglongLee avatar zhanglongLee commented on July 28, 2024

Promise 原理

Promise 是异步编程的一种解决方案: 从语法上讲,promise是一个对象,从它可以获取异步操作的消息;从本意上讲,它是承诺,承诺它过一段时间会给你一个结果。 promise有三种状态:pending(等待态),fulfiled(成功态),rejected(失败态);状态一旦改变,就不会再变。创建promise实例后,它会立即执行。

解决问题

promise是用来解决两个问题的:

  • 回调地狱,代码难以维护, 常常第一个的函数的输出是第二个函数的输入这种现象
  • promise可以支持多个并发的请求,获取并发请求中的数据
  • 这个promise可以解决异步的问题,本身不能说promise是异步的

方法

Promise是一个构造函数,自己身上有all、reject、resolve这几个方法,原型上有then、catch等方法。

手写一个Promise

class MyPromise {
  // 构造方法
  constructor(executor) {
    // 初始化值
    this.initValue()
    // 初始化this指向
    this.initBind()
    // Promise中有throw的话,就相当于执行了reject。这就要使用try catch了
    try {
      // 执行传进来的函数
      executor(this.resolve, this.reject)
    } catch (error) {
      // 捕捉到错误直接执行reject
      this.reject(error)
    }
  }

  initValue() {
    // 初始化值
    this.PromiseResult = null // 最终的值
    this.PromiseState = 'pending' // 状态
    this.onFulfilledCallbacks = [] // 保存成功回调
    this.onRejectedCallbacks = [] // 保存失败回调
  }
  initBind() {
    // 初始化this
    this.resolve = this.resolve.bind(this)
    this.reject = this.reject.bind(this)
  }
  resolve(value) {
    // state是不可变的
    if (this.PromiseState != 'pending') { return }
    // 如果执行resolve,状态变为fulfilled
    this.PromiseState = 'fulfilled'
    // 终值为传进来的值
    this.PromiseResult = value
    // 执行保存的成功回调
    while (this.onFulfilledCallbacks.length) {
      this.onFulfilledCallbacks.shift()(this.PromiseResult)
    }
  }
  reject(reason) {
    // state是不可变的
    if (this.PromiseState != 'pending') { return }
    // 如果执行reject,状态变为rejected
    this.PromiseState = 'rejected'
    // 终值为传进来的reason
    this.PromiseResult = reason
    // 执行保存的失败回调
    while (this.onRejectedCallbacks.length) {
      this.onRejectedCallbacks.shift()(this.PromiseResult)
    }
  }
  then(onFulfilled, onRejected) {
    // 接收两个回调 onFulfilled, onRejected

    // 参数校验,确保一定是函数
    onFulfilled = typeof onFulfilled === 'function' ? onFulfilled : val => val
    onRejected = typeof onRejected === 'function' ? onRejected : reason => { throw reason }

    // 封装一个thenPromise
    var thenPromise = new MyPromise((resolve, reject) => {

      const resolvePromise = cb => {
        setTimeout(() => {
          try {
            const x = cb(this.PromiseResult)
            if (x === thenPromise) {
              // 不能返回自身
              throw new Error('不能返回自身')
            }
            if (x instanceof MyPromise) {
              // 如果返回值是Promise
              // 如果返回值是promise对象,返回值为成功,新promise就是成功
              // 如果返回值是promise对象,返回值为失败,新promise就是失败
              // 谁知道返回的promise是失败成功?只有then知道
              x.then(resolve, reject)
            } else {
              // 非Promise就直接成功
              resolve(x)
            }
          } catch (error) {
            // 处理报错
            reject(error)
            throw new Error(error)
          }
        }, 0)
      }

      if (this.PromiseState === 'fulfilled') {
        // 如果当前是成功状态,执行第一个回调
        resolvePromise(onFulfilled)
      } else if (this.PromiseState === 'rejected') {
        // 如果当前是失败状态,执行第二个回调
        resolvePromise(onRejected)
      } else if (this.PromiseState === 'pending') {
        // 如果状态为待定状态,暂时保存两个回调
        this.onFulfilledCallbacks.push(resolvePromise.bind(this, onFulfilled))
        this.onRejectedCallbacks.push(resolvePromise.bind(this, onRejected))
      }

    })
    // 返回这个包装的Promise
    return thenPromise
  }

  /**
   * all
   * 接收一个Promise数组,数组中如有非Promise项,则此项当做成功
   * 如果所有Promise都成功,则返回成功结果数组
   * 如果有一个Promise失败,则返回这个失败结果
   * @param {Array} promise
   * @returns
   */
  static all(promise) {
    const result = []
    let count = 0
    return new MyPromise((resolve, reject) => {
      const addData = (index, value) => {
        result[index] = value
        count++
        if (count === result.length) {
          resolve(result)
        }
      }
      promise.forEach((promise, index) => {
        if (promise instanceof MyPromise) {
          promise.then(res => {
            addData(index, res)
          }, err => reject(err))
        } else {
          addData(index, promise)
        }
      })
    })
  }

  /**
   * race
   * 接收一个Promise数组,数组中如有非Promise项,则此项当做成功
   * 哪个Promise最快得到结果,就返回那个结果,无论成功失败
   * @param {Array} promise
   * @returns
   */
  static race(promise) {
    return new MyPromise((resolve, reject) => {
      promise.forEach((promise, index) => {
        if (promise instanceof MyPromise) {
          promise.then(res => {
            resolve(res)
          }, err => {
            reject(err)
          })
        } else {
          resolve(promise)
        }
      })
    })
  }

  /**
   * allSettled
   * 接收一个Promise数组,数组中如有非Promise项,则此项当做成功
   * 把每一个Promise的结果,集合成数组,返回
   * @param {Array} promise
   * @returns
   */
  static allSettled(promise) {
    const result = []
    let count = 0
    return new MyPromise((resolve, reject) => {
      const addData = (status, value, i) => {
        result[i] = {
          status,
          value
        }
        count++
        if (count === result.length) {
          resolve(result)
        }
      }
      promise.forEach((promise, index) => {
        if (promise instanceof MyPromise) {
          promise.then(res => {
            addData('fulfilled', res, index)
          }, err => {
            addData('rejected', err, index)
          })
        } else {
          addData('fulfilled', promise, index)
        }
      })
    })
  }

  /**
   * any
   * any与all相反
   * 接收一个Promise数组,数组中如有非Promise项,则此项当做成功
   * 如果有一个Promise成功,则返回这个成功结果
   * 如果所有Promise都失败,则报错
   * @param {Array} promise
   * @returns
   */
  static any(promise){
    return new MyPromise((resolve,reject)=>{
      let count = 0
      promise.forEach((promise,index)=>{
        promise.then(res=>{
          resolve(res)
        },err=>{
          count++
          if(count === promise.length){
            reject(new AggregateError('All promises were rejected'))
          }
        })
      })
    })
  }
}

from trisome.

Related Issues (20)

Recommend Projects

  • React photo React

    A declarative, efficient, and flexible JavaScript library for building user interfaces.

  • Vue.js photo Vue.js

    🖖 Vue.js is a progressive, incrementally-adoptable JavaScript framework for building UI on the web.

  • Typescript photo Typescript

    TypeScript is a superset of JavaScript that compiles to clean JavaScript output.

  • TensorFlow photo TensorFlow

    An Open Source Machine Learning Framework for Everyone

  • Django photo Django

    The Web framework for perfectionists with deadlines.

  • D3 photo D3

    Bring data to life with SVG, Canvas and HTML. 📊📈🎉

Recommend Topics

  • javascript

    JavaScript (JS) is a lightweight interpreted programming language with first-class functions.

  • web

    Some thing interesting about web. New door for the world.

  • server

    A server is a program made to process requests and deliver data to clients.

  • Machine learning

    Machine learning is a way of modeling and interpreting data that allows a piece of software to respond intelligently.

  • Game

    Some thing interesting about game, make everyone happy.

Recommend Org

  • Facebook photo Facebook

    We are working to build community through open source technology. NB: members must have two-factor auth.

  • Microsoft photo Microsoft

    Open source projects and samples from Microsoft.

  • Google photo Google

    Google ❤️ Open Source for everyone.

  • D3 photo D3

    Data-Driven Documents codes.