likes
comments
collection
share

地狱回调解决方法promise-async

作者站长头像
站长
· 阅读数 15

地狱回调解决方法promise-async 其实这个问题已经是老生常谈了

这个问题在后端就没有,其实后端不是没有,而是没有必要

前端这个问题主要就是集中在请求中

ajax时代

可能有大大写过这样的代码

function ajax(params,callback){
  
}


ajax({},function (res){
  ajax({},function (res){
    ajax({},function (res){
      ajax({},function (res){
        ajax({},function (res){
          ajax({},function (res){
            ajax({},function (res){
              ajax({},function (res){
                ajax({},function (res){
                  ajax({},function (res){
                    ajax({},function (res){
                      ajax({},function (res){
                        ajax({},function (res){

                        })
                      })
                    })
                  })
                })
              })
            })
          })
        })
      })
    })
  })
})

这个代码让你头皮发麻,代码层级看的都头大,个人表示不想看,所以这个问题肯定是有解决方案的,也就是Promise

Promise

使用Promise上面的代码就可以转成下面的代码

先包装一下

function ajax2(params) {
  return new Promise(resolve => {
    ajax(params,resolve)
  })
}

然后代码就可以这样写

ajax2({})
  .then(res=>{
    return ajax2({})
  })
  .then(res=>{
    return ajax2({})
  })
  .then(res=>{
    return ajax2({})
  })
  .then(res=>{
    return ajax2({})
  })
  .then(res=>{
    return ajax2({})
  })
  .then(res=>{
    return ajax2({})
  })
  .then(res=>{
    return ajax2({})
  })
  .then(res=>{
    return ajax2({})
  })
  .then(res=>{
    return ajax2({})
  })
  .then(res=>{
    return ajax2({})
  })
  .then(res=>{
    return ajax2({})
  })

这样看着就要好的多,但是既然还是等待上面的方法执行完成再执行下面的代码,所以就又有了async/await

async/await

async/await其实是promise的语法糖,所以可以直接接入promise,声明了async的函数一定会返回一个Promise,如果你写了返回值那么返回的promise.then里面的回调参数就是你返回的值,如果你没有写返回写返回值,那么就会返回一个Promise<void>

使用async/await上面的代码就可以变成下面的代码

async function runAjax2() {
  await ajax2({})
  await ajax2({})
  await ajax2({})
  await ajax2({})
  await ajax2({})
  await ajax2({})
  await ajax2({})
  await ajax2({})
  await ajax2({})
  await ajax2({})
  await ajax2({})
}

runAjax2()

看着清爽无比,个人在顺序请求中也是最喜欢用这个,得益于babel无需担心js的兼容性问题O(∩_∩)O哈哈~

注意

这些回调问题在最后的async中基本就可以解决,尤其是下一个请求需要用到上一个请求的参数,像使用promise的then去搞定这个问题,你都要裂开

举个例子,还是用的Promise里面的代码,如果我第4个请求要用第一个请求的结果作为参数,那么我就只能在外部定义变量去接这个结果,然后再放到请求参数里面去

// 比如我在第4个请求中要用1的请求的结果
let ajax2Res = {

}
ajax2({})
  .then(res1=>{
    ajax2Res.res1 = res1
    return ajax2({}) // 2
  })
  .then(res=>{
    return ajax2({})
  })
  .then(res=>{
    return ajax2(ajax2Res.res1) // 4
  })
  .then(res=>{
    return ajax2({})
  })
  .then(res=>{
    return ajax2({})
  })
  .then(res=>{
    return ajax2({})
  })
  .then(res=>{
    return ajax2({})
  })
  .then(res=>{
    return ajax2({})
  })
  .then(res=>{
    return ajax2({})
  })
  .then(res=>{
    return ajax2({})
  })
  .then(res=>{
    return ajax2({})
  })

但是如果是在async中就没有必要这样写,我们就可以直接这样写

async function runAjax2() {
  const res1 = await ajax2({}) // 1
  await ajax2({})
  await ajax2({})
  await ajax2(res1) // 4
  await ajax2({})
  await ajax2({})
  await ajax2({})
  await ajax2({})
  await ajax2({})
  await ajax2({})
  await ajax2({})
}

runAjax2()

这样是不是就很清爽

最后

个人建议是能用async就用async

我也是这样使用顺序 async > promise > callback

当然,有的同学就问为什么不用yield和*function,个人只能表示,这个玩意不是很友好啊,看着就像C语言的指针函数一样了,不过babel对async/await的编译封装就是用的这个,有兴趣的同学可以去看怎么编译的