码迷,mamicode.com
首页 > 其他好文 > 详细

回调地狱的解决办法

时间:2019-08-19 23:06:28      阅读:406      评论:0      收藏:0      [点我收藏+]

标签:ken   log   erro   微信   通过   成功   实例   ack   rom   

回调是地狱是容易遇到的坑,解决方案是使用promise

碎碎念

相信各位玩家肯定都写过下面的这样代码:


// 同时发送两个请求
let url = 'xxxxx', url1 = 'xx'
$.ajax({
  url,
  success(data) {
    $.ajax({
       url: url1,
       success(data) {
          console.log('done')
       }
    })
  }
})

是不是很贴切?
有可能有的新手小伙伴连回调都不知道,这里给大家普及一下

/*
** time - 时间
** call  - 回调
*/

let outTime = (time, call) => {
  setTimeout(()=> {
    call()
  }, time)
}

// 使用

outTime(2000,()=>{
  console.log('done')
})

这就是最简单最常见场景下的回调了. 在我刚学js时候,遇到一个困惑
在尝试发起请求的时候, 第一会遇到跨域请求, 还有就是不是同步代码的困惑
技术图片
所谓的同步代码,给大家上一段当初我写的代码(超害羞??)

// 假设我封装了一个方法来发起`http`请求: func
let data = func({
  url: 'xxx',
  data: { path: 'xxx' }
})
console.log(data)

当打印之后永远都是undefined
技术图片
诶,我就不信了

func({
  url: 'xxx',
  data: { path: 'xxx' },
  success(data) {
    window.fuck = data
  }
})
let fuckInter  = setInterval(()=> {
  if (window.fuck) next()
},50)

function next() {
  // 接下来的代码..
}

先别笑,我当初还真是这么解决的..
我尝试读了一下jq源码,发现它实现了一种所谓的callback回调函数
(很惭愧的是,现在都不能跟观众老爷们说明白这是怎么一回事)

通过这件事,让我想起我一次面试,我面的是小程序,以下对话

Ta: 小程序的网络请求不太完善,你有什么办法能够优化一下网络库,满足自己需求

Me: 写一个公共文件,写一个回调函数, 把需要的参数这些都包裹起来并封装

Ta: (内心一团乱麻..) 还有...有吗?

Me: (又说了一遍)

Ta: 那好像和微信的原生库没什么区别

被小瞧了,那货其实是想问,请求加密之类的,我说用token(你又没说功能,我怎么知道...)

解决方案

回到正题,接下来就说解决方案了
vuejs 官方推荐的 axios 就是使用 promise, 我有幸在几个项目中使用过,但是没有深究其原理

;(async ()=> {
 return new Promise(( rcv, rjt)=> {
   setTimeout(()=> {
      rcv('fuck')
   }, 5000)
 })
})()
  .then(r=> {
     console.log(r) // 'fuck'
   })

promise 接受两个参数: resolve, reject
第一个参数是操作成功,第二个是在操作错误

值得一提的,如果你打印这个对象的话,它返回的会是一个:

let pro = new Promise((rsv,rjt)=> {
   console.log('xxx')
})
console.log(pro)
/*
** Promise { pending(进行中)、fulfilled(已成功)和 rejected(已失败)}
**/

在实例创建后,你可以使用then来处理成功catch来处理操作错误
现在我们就可以使用它来重写$.ajax方法

function proAjax() {
  let url = 'xxx' // 假装存在咯
  return new Promise((rcv, rjt)=> {
    $.ajax({
      url,
      success: data => rcv(data),
      error: e=> rjt(e)
    })
  })
}
// 用法

proAjax()
  .then(r=> {
   console.log('我拿到数据了,真好')
  })
  .catch(e=> {
    throw new Error(e)
  }

为了让它更像同步代码,我们可以使用async await

async function func() {
  let data await new Promise((rcv,rjt)=> {
     $.ajax(
       url,
       success: data => rcv(data)
     )
  })
  return data
}
func()
  .then(r=> {
     console.log('拿到数据了,皮卡丘!')
  })

async 我不太能够解释这是什么,只知道它会返回一个promise,所以它有then | catch 方法,至于await 它只能在async函数里使用,它可以获取promise返回值(这里不知道怎么表达),就可以实现所谓的同步代码

报错信息也很有用哦

总结

这货解决了回调地狱, 在本篇文中并未提及在promise下的多"回调",不过在每次then下由可以return promise对象,接下来就你懂的~

拥抱新技术,拥抱开源

20190819

回调地狱的解决办法

标签:ken   log   erro   微信   通过   成功   实例   ack   rom   

原文地址:https://www.cnblogs.com/kozo4/p/11379873.html

(0)
(0)
   
举报
评论 一句话评论(0
登录后才能评论!
© 2014 mamicode.com 版权所有  联系我们:gaon5@hotmail.com
迷上了代码!