原文连接: https://www.xksblog.top/talk-...
见到wx.request
的第一眼,就让我想起了$.ajax
这东西,使用起来确实有不少不方便,不能忍,幸亏小程序是支持ES6语法的,因此可使用promise稍加改造。html
先来讲说wx.request为何不能忍。ajax
Page({ data: { myData: '' }, // loadMyData函数用于打印myData的值 loadMyData () { console.log('获取到的数据为:' + this.data.myData) }, // 生命周期函数onload用于监听页面加载 onload: function () { wx.request({ url: 'https://api', // 某个api接口地址 success: res => { console.log(res.data) this.setData({ myData: res.data }) console.log(this.data.myData) } }) // 调用以前的函数 this.loadMyData() } })
而后咱们会在控制台到这样的结果:json
这实际上是一个很简单的异步问题,wx.request是异步请求,JS不会等待wx.request执行完毕再往下执行,因此JS按顺序会先执行this.loadMyData(),等服务器返回数据之后,loadMyData()早就执行完了,固然也就没有拿到值啦。小程序
其实咱们在同步流程中才说“返回”,异步没有“返回”这个概念(或者说异步返回是没有意义的),异步对应的是“回调”,也就是说,对于一个异步函数,咱们应该传入一个“回调函数”来接收结果。微信小程序
最简单的解决方案,就是把须要使用异步数据的函数写在回调里:api
... onload: function () { wx.request({ url: 'https://api', // 某个api接口地址 success: res => { console.log(res.data) this.setData({ myData: res.data }) console.log(this.data.myData) // 把使用数据的函数写在回调函数success中 this.loadMyData() } }) }
这样就能够正确输出了:promise
可是若是逻辑复杂,须要多层异步操做,会出现怎么样的状况呢?服务器
asyncFn1(function(){ //... asyncFn2(function(){ //... asyncFn3(function(){ //... asyncFn4(function(){ //... asyncFn5(function(){ //... }); }); }); }); });
有没有感受头皮发麻?什么优雅什么可读性,瞬间荡然无存,这就是恐怖的“回调地狱”(Callback Hell)。微信
而咱们发现,微信小程序的网络请求wx.request,也正是这种依靠回调函数的形式,相似于之前的$.ajax
,它在逻辑复杂、页面执行顺序要求多的状况下,弊端也是很明显的。不过好在小程序支持ES6,咱们能够尽情地拥抱Promise!网络
Promise这东西简单说来就是,它能够将异步的执行逻辑和结果处理分离,摒弃了一层又一层的回调嵌套,使得处理逻辑更加清晰。想具体了解的还请自行查找资料。
如今咱们就用Promise包装一下wx.request:
/** * requestPromise用于将wx.request改写成Promise方式 * @param:{string} myUrl 接口地址 * @return: Promise实例对象 */ const requestPromise = myUrl => { // 返回一个Promise实例对象 return new Promise((resolve, reject) => { wx.request({ url: myUrl, success: res => resolve(res) }) }) } // 我把这个函数放在了utils.js中,这样在须要时能够直接引入 module.exports = requestPromise
如今再使用试试:
// 引用模块 const utilApi = require('../../utils/util.js') Page({ ... // 生命周期函数onload用于监听页面加载 onLoad: function () { utilApi.requestPromise("https://www.bilibili.com/index/ding.json") // 使用.then处理结果 .then(res => { console.log(res.data) this.setData({ myData: res.data }) console.log(this.data.myData) this.loadMyData() }) } })
结果和使用回调函数一致。当有多个异步请求时,直接不断地.then(fn)去处理便可,逻辑清晰。
固然,这里只是写了一个最简单的Promise函数,还不完整。更完整的Promise化wx.request,等之后业务须要再完善吧。另外各类小程序开发框架也都有了现成的promise化API,拿来即用。