wx.request封装解决回调地狱(转载)

原文链接:www.xksblog.top/talk-about-…

见到wx.request的第一眼,就让我想起了$.ajax这东西,使用起来确实有很多不方便,不能忍,幸好小程序是支持ES6语法的,所以可以使用promise稍加改造。

先来说说wx.request为什么不能忍。

铺垫:“看得见却抓不住“的异步请求


    
    
  1. Page({
  2. data: {
  3. myData: ''
  4. },
  5. // loadMyData函数用于打印myData的值
  6. loadMyData () {
  7. console.log( '获取到的数据为:' + this.data.myData)
  8. },
  9. // 生命周期函数onload用于监听页面加载
  10. onload: function () {
  11. wx.request({
  12. url: 'https://api', // 某个api接口地址
  13. success: res => {
  14. console.log(res.data)
  15. this.setData({
  16. myData: res.data
  17. })
  18. console.log( this.data.myData)
  19. }
  20. })
  21. // 调用之前的函数
  22. this.loadMyData()
  23. }
  24. })
  25. 复制代码

然后我们会在控制台到这样的结果:

这其实是一个很简单的异步问题,wx.request是异步请求,JS不会等待wx.request执行完毕再往下执行,所以JS按顺序会先执行this.loadMyData(),等服务器返回数据以后,loadMyData()早就执行完了,当然也就没有拿到值啦。

其实我们在同步流程中才说“返回”,异步没有“返回”这个概念(或者说异步返回是没有意义的),异步对应的是“回调”,也就是说,对于一个异步函数,我们应该传入一个“回调函数”来接收结果。

初步解决:通过回调接收结果

最简单的解决方案,就是把需要使用异步数据的函数写在回调里:


    
    
  1. ...
  2. onload: function () {
  3. wx.request({
  4. url: 'https://api', // 某个api接口地址
  5. success: res => {
  6. console.log(res.data)
  7. this.setData({
  8. myData: res.data
  9. })
  10. console.log( this.data.myData)
  11. // 把使用数据的函数写在回调函数success中
  12. this.loadMyData()
  13. }
  14. })
  15. }
  16. 复制代码

这样就可以正确输出了:

但是如果逻辑复杂,需要多层异步操作,会出现怎么样的情况呢?


    
    
  1. asyncFn1( function(){
  2. //...
  3. asyncFn2( function(){
  4. //...
  5. asyncFn3( function(){
  6. //...
  7. asyncFn4( function(){
  8. //...
  9. asyncFn5( function(){
  10. //...
  11. });
  12. });
  13. });
  14. });
  15. });
  16. 复制代码

有没有感觉头皮发麻?什么优雅什么可读性,瞬间荡然无存,这就是恐怖的“回调地狱”(Callback Hell)。

而我们发现,微信小程序的网络请求wx.request,也正是这种依靠回调函数的形式,类似于以前的$.ajax,它在逻辑复杂、页面执行顺序要求多的情况下,弊端也是很明显的。不过好在小程序支持ES6,我们可以尽情地拥抱Promise!

使用Promise包装wx.request

Promise这东西简单说来就是,它可以将异步的执行逻辑和结果处理分离,摒弃了一层又一层的回调嵌套,使得处理逻辑更加清晰。想具体了解的还请自行查找资料。

现在我们就用Promise包装一下wx.request:


    
    
  1. /**
  2. * requestPromise用于将wx.request改写成Promise方式
  3. * @param:{string} myUrl 接口地址
  4. * @return: Promise实例对象
  5. */
  6. const requestPromise = myUrl => {
  7. // 返回一个Promise实例对象
  8. return new Promise( (resolve, reject) => {
  9. wx.request({
  10. url: myUrl,
  11. success: res => resolve(res)
  12. })
  13. })
  14. }
  15. // 我把这个函数放在了utils.js中,这样在需要时可以直接引入
  16. module.exports = requestPromise
  17. 复制代码

现在再使用试试:


    
    
  1. // 引用模块
  2. const utilApi = require( '../../utils/util.js')
  3. Page({
  4. ...
  5. // 生命周期函数onload用于监听页面加载
  6. onLoad: function () {
  7. utilApi.requestPromise( "https://www.bilibili.com/index/ding.json")
  8. // 使用.then处理结果
  9. .then( res => {
  10. console.log(res.data)
  11. this.setData({
  12. myData: res.data
  13. })
  14. console.log( this.data.myData)
  15. this.loadMyData()
  16. })
  17. }
  18. })
  19. 复制代码

结果和使用回调函数一致。当有多个异步请求时,直接不断地.then(fn)去处理即可,逻辑清晰。

当然,这里只是写了一个最简单的Promise函数,还不完整。更完整的Promise化wx.request,等以后业务需要再完善吧。另外各种小程序开发框架也都有了现成的promise化API,拿来即用。

转载于:https://juejin.im/post/5bac8e866fb9a05cf23001fe

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值