回调地狱的解决办法

Posted kozo4

tags:

篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了回调地狱的解决办法相关的知识,希望对你有一定的参考价值。

回调是地狱是容易遇到的坑,解决方案是使用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

以上是关于回调地狱的解决办法的主要内容,如果未能解决你的问题,请参考以下文章

promise解决回调地狱

什么是地狱回调?解决回调地狱的两种方法

回调地狱以及用promise怎么解决回调地狱

解决回调地狱问题

解决回调地狱

基于PROMISE解决回调地狱问题