• Promise原理


    v1

    仅能处理异步的成功和失败

    实现

    // no-log
    // 自定义函数`Promi`来模拟`Promise`
    function ProMi(executor) {
      let that = this
      that.status = 'pending'
      that.failCallBack = undefined
      that.successCallback = undefined
      executor(resolve.bind(that), reject.bind(that))
    
      function resolve(params) {
        if (that.status === 'pending') {
          that.status = 'success'
          if (that.successCallback) {
            that.successCallback(params)
          } else {
            console.error('未传入成功回调')
          }
        }
      }
    
      function reject(params) {
        if (that.status === 'pending') {
          that.status = 'fail'
          if (that.failCallBack) {
            that.failCallBack(params)
          } else {
            console.error('未传入失败回调')
          }
        }
      }
    }
    
    ProMi.prototype.then = function (successCallback, failCallBack) {
      this.successCallback = successCallback
      this.failCallBack = failCallBack
    }
    

    测试一下Promi

    new ProMi(function (resolve, reject) {
      setTimeout(() => {
        resolve('{"msg": "Hello world!"}')
      }, 1000)
    }).then((data) => {
      // log-async
      console.log(data)
    }, null)
    
    // 由于 try catch只能捕捉同步方法的错误,这里假装有错误
    new ProMi(function (resolve, reject) {
      setTimeout(() => {
        reject('{"msg": "我是一个一个错误"}')
      }, 1000)
    }).then(null, (err) => {
      // log-async
      console.log(err)
    })
    

    这便是,Promise的最基本原理。

    bug

    但是当我们使用如下同步代码测试时,发现并不凑效(报错:未传入成功/失败回调,需要查看控制台)

    new ProMi(function (resolve, reject) {
      // 这是一段同步代码
      let sum = 0
      for (let i = 0; i < 10000; i++) {
        sum = sum + i
      }
      resolve(sum)
    }).then((data) => {
      // 不走这,因为没有传入成功的回调函数
      // log-async
      console.log(data)
    })
    
    new ProMi(function (resolve, reject) {
      // 这是一段同步代码
      try {
        abc.alert(1)
      } catch (e) {
        reject(e.message)
      }
    }).then(null, (err) => {
      // 不走这,因为没有失败的回调函数
      // log-async
      console.log(err)
    })
    

    v2

    能处理异步+同步的成功和失败

    实现

    对于同步方法,failCallBack不能及时传入,此时只需要修改下 resolve 和 reject

    function ProMise(executor) {
      let that = this
      that.status = 'pending'
      that.failCallBack = undefined
      that.successCallback = undefined
      that.error = undefined
      executor(resolve.bind(that), reject.bind(that))
    
      function resolve(params) {
        if (that.status === 'pending') {
          that.status = 'success'
          if (that.successCallback) {
            that.successCallback(params)
          } else {
            // log-async
            console.log('未第一时间传入成功回调,若干毫秒后将重试')
            setTimeout(() => {
              that.successCallback(params)
            }, 1)
          }
        }
      }
    
      function reject(params) {
        if (that.status === 'pending') {
          that.status = 'fail'
          if (that.failCallBack) {
            that.failCallBack(params)
          } else {
            // log-async
            console.log('未第一时间传入失败回调,若干毫秒后将重试')
            setTimeout(() => {
              that.failCallBack(params)
            }, 1)
          }
        }
      }
    }
    
    ProMise.prototype.then = function (full, fail) {
      this.successCallback = full
      this.failCallBack = fail
    }
    window.ProMise = ProMise
    
    // 再测试一遍同步回调
    new ProMise(function (resolve, reject) {
      try {
        abc.alert(1)
      } catch (e) {
        reject(e.message)
      }
    }).then(null, (err) => {
      // log-async
      console.log(err)
    })
    
    new ProMise(function (resolve, reject) {
      let start = new Date().getTime()
      let sum = 0
      for (let i = 0; i < 3000 * 3000; i++) {
        sum = sum + i
      }
      let end = new Date().getTime()
      // log-async
      console.log(end - start)
      resolve(sum)
    }).then(data => {
      // log-async
      console.log(data)
    })
    
  • 相关阅读:
    关于ubantu在VMWARE里安装时出现'SMBus Host Controller not enabled'
    临时备忘录
    第七届 山东ACM热身赛 Dwarf Tower
    数学问题题目连接
    蓝桥杯2016决赛 凑平方数
    博弈整理(取物)
    格子刷油漆(DP)
    蓝桥杯第六届总决赛B组
    蓝桥杯第五届决赛B组
    蓝桥杯第四届总决赛
  • 原文地址:https://www.cnblogs.com/oceans/p/promise.html
Copyright © 2020-2023  润新知