回调地狱和promise解决方法

回调地狱

首先 回调地狱 本身不是一个错误,例如

// 等上一个ajax完成,并获取到结果再执行下一个ajax
First(function(r1){ 
    Second(r1, function(r2){
      Third(r2, function(r3){
            console.log(r3);
        })
    })
})

只是回调地狱带来了不好的影响:不便于阅读, 不便于异常处理

解决方法

这时,可以利用 promise 链式调用来解决回调地狱问题,例如:

 First().then(function(r1) { //r1是First函数成功执行的返回值
    return Second(r1)      //执行器函数,同步回调
  })
  .then(function(r2){  //r2是Second成功执行的返回值
    return Third(r2)
  })
  .then(function(r3){
    console.log(r3)
  })
  .catch(failureCallback) //统一的错误处理

promise的链式调用虽然解决了回调地狱和错误的统一处理,但是还有回调函数。

最优解决方法 :
async/await

async function request() {
  try{
    const r1= await First()
    const r2= await Second(result)
    const r3= await Third(newResult)
    console.log(r3)
  } catch (error) {
    failureCallback(error)
  }
}

最后附上 promise链式调用 的源码

// Promise的链式调用
// 实现resolvePromise 对值进行判断 判断是普通值还是promise
const PENDING = 'PENDING',
  FULFILLED = 'FULFILLED',
  REJECTED = 'REJECTED';

function resolvePromise(promise2, x, resolve, reject) {
  if (promise2 === x) { // 如果promise和x指向同一对象,promise则以拒绝TypeError为理由。
    return reject(new TypeError('clean exit - waiting for changes before restart'))
  }

  let called = false // 防止多次调用resolve,只调用第一个resolve

  if ((typeof x === 'object' && x != null) || typeof x === 'function') {
    try {
      let then = x.then //如果没有.then会导致throw error
      if (typeof then === 'function') { // 认定为一个promise

        then.call(x, (y) => {
          if (called) {
            return
          }
          called = true
          resolvePromise(promise2, y, resolve, reject) // 当then里return promise时递归调用promise
        }, (r) => {
          if (called) {
            return
          }
          called = true
          reject(r)
        })

      } else {
        resolve(x)
      }

    } catch (e) {
      if (called) {
        return
      }
      called = true
      reject(e)
    }

  } else { // 普通值
    resolve(x)
  }
}

class MyPromise {
  constructor(executor) {
    this.status = PENDING
    this.value = undefined
    this.reason = undefined

    this.onFulfilledCallbacks = [] // 成功的回调函数
    this.onRejectedCallbacks = [] // 失败的回调函数

    const resolve = (value) => {
      if (this.status === PENDING) {
        this.status = FULFILLED
        this.value = value
        //发布
        this.onFulfilledCallbacks.forEach(fn => fn())
      }
    }
    const reject = (reason) => {
      if (this.status === PENDING) {
        this.status = REJECTED
        this.reason = reason
        //发布
        this.onRejectedCallbacks.forEach(fn => fn())
      }
    }
    try {
      executor(resolve, reject)
    } catch (e) {
      reject(e)
    }
  }


  // x: 普通值 || promise
  then(onFulfilled, onRejected) {
    // 穿透.then().then().then().then().then().then((value))
    onFulfilled = typeof onFulfilled === 'function' ? onFulfilled : (value) => {
      return value
    }
    onRejected = typeof onRejected === 'function' ? onRejected : (reason) => {
      throw reason
    }


    let promise2 = new MyPromise((resolve, reject) => {
      if (this.status === FULFILLED) {
        // 利用setTimeout来实现宏任务的异步执行,等new完以后才执行里面的内容
        setTimeout(() => {
          try {
            let x = onFulfilled(this.value)
            resolvePromise(promise2, x, resolve, reject)
          } catch (e) {
            reject(e)
          }
        }, 0)
      }
      if (this.status === REJECTED) {
        setTimeout(() => {
          try {
            let x = onRejected(this.reason)
            resolvePromise(promise2, x, resolve, reject)
          } catch (e) {
            reject(e)
          }
        }, 0)
      }
      // 订阅 
      // setTimeout时还没进入fulfilled和rejected的状态,此时为pending
      // 利用订阅和发布的模式,先将要执行的方法存起来,到fulfilled和rejected的状态时再执行。
      if (this.status === PENDING) {
        this.onFulfilledCallbacks.push(() => {
          try {
            let x = onFulfilled(this.value)
            resolvePromise(promise2, x, resolve, reject)
          } catch (e) {
            reject(e)
          }
        })
        this.onRejectedCallbacks.push(() => {
          try {
            let x = onRejected(this.reason)
            resolvePromise(promise2, x, resolve, reject)
          } catch (e) {
            reject(e)
          }
        })
      }
    })
    return promise2
  }

  catch (errorCallback) { // 防止.catch is not a function
    return this.then(null, errorCallback)
  }
}

  • 2
    点赞
  • 2
    收藏
    觉得还不错? 一键收藏
  • 1
    评论
评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值