WeChat-SmallProgram:微信小程序中使用Async-await方法异步请求变为同步请求
微信小程序中有些 Api 是异步的,无法直接进行同步处理。例如:wx.request、wx.showToast、wx.showLoading 等。如果需要同步处理,可以使用如下方法:
提示:Async-await 方法属于ES7语法,在小程序开发工具中如果勾选es6转es5, 会报错:
ReferenceError: regeneratorRuntime is not defined
需要解决的问题都有哪些:
1、截止到发文前小程序还不支持ES7的语法,我们到底能不能用?
2、撸的方式又是怎样的?
实践的方式如下:
第一个问题:
虽然小程序不支持,但是我们可以引入js库啊。双手奉上 facebook 的开源库 regenerator 下载 'packages/regenerator-runtime' 将这个文件放到自己小程序项目下的 utils 或者 lib 文件夹下。
总共就23K不要担心包体积的问题。
然后在使用async-awiat的页面中引入
const regeneratorRuntime = require('../../lib/regenerator-runtime/runtime')
第二个问题:
Async 跟 Await 的用法。
Async - 定义异步函数(async function someName(){...})
自动把函数转换为 Promise
当调用异步函数时,函数返回值会被 resolve 处理
异步函数内部可以使用 await
Await - 暂停异步函数的执行 (var result = await someAsyncCall();)
当使用在 Promise 前面时,await 等待 Promise 完成,并返回 Promise 的结果
await 只能和 Promise 一起使用,不能和 callback 一起使用
await 只能用在 async 函数中
案例代码(一):
在根目录下新建api文件夹,里面新建index.js
// request get 请求 const getData = (url, param) => { return new Promise((resolve, reject) => { wx.request({ url: url, method: 'GET', data: param, success (res) { console.log(res) resolve(res.data) }, fail (err) { console.log(err) reject(err) } }) }) } // request post 请求 const postData = (url, param) => { return new Promise((resolve, reject) => { wx.request({ url: url, method: 'POST', data: param, success (res) { console.log(res) resolve(res.data) }, fail (err) { console.log(err) reject(err) } }) }) } // loading加载提示 const showLoading = () => { return new Promise((resolve, reject) => { wx.showLoading({ title: '加载中...', mask: true, success (res) { console.log('显示loading') resolve(res) }, fail (err) { reject(err) } }) }) } // 关闭loading const hideLoading = () => { return new Promise((resolve) => { wx.hideLoading() console.log('隐藏loading') resolve() }) } module.exports = { getData, postData, showLoading, hideLoading }
在入口文件 app.js 中引入:
//app.js const api = require('./api/index') App({ onLaunch: function () { }, // 全局数据中暴露api globalData: { api } })
在需要使用api 的页面中处理如下:
const app = getApp() const api = app.globalData.api const regeneratorRuntime = require('../../lib/regenerator-runtime/runtime') Page({ onLoad() { this.init() }, // 初始化 async init() { console.log("日志打印(1)"); await api.showLoading() // 显示loading console.log("日志打印(2)"); await this.getList() // 请求数据 console.log("日志打印(3)"); await api.hideLoading() // 等待请求数据成功后,隐藏loading console.log("日志打印(4)"); }, // 获取列表 getList() { return new Promise((resolve, reject) => { api.getData('http://127.0.0.1:9003/list', { token: "043c00e6c7ff021e8cc4d394d3264cb5e8c" }).then((res) => { this.setData({ list: res }) console.log("返回数据"); resolve() }) .catch((err) => { reject(err) }) }) }, })
主要看日志的打印顺序 查看执行流程 自行改动 异步|同步 查看效果。
案例代码(二):
// pages/index/index.js //index.js import regeneratorRuntime from '../../utils/runtime.js' const moment = require('../../utils/mp-moment') //获取应用实例 const app = getApp() Page({ /** * 页面的初始数据 */ data: { }, /** * 生命周期函数--监听页面加载 */ onLoad: function (options) { let that = this // 同步执行异步函数 that.testAsync() // 异步执行异步函数 // that.testSync() }, async testAsync() { let that = this console.log(moment(Date.now()).format('YYYY-MM-DD HH:mm:ss') + ' testAsync start') console.log('show loading') let resultOne = await that.getValueOne(); console.log(moment(Date.now()).format('YYYY-MM-DD HH:mm:ss') + resultOne) let resultTwo = await that.getValueTwo(); console.log(moment(Date.now()).format('YYYY-MM-DD HH:mm:ss') + resultTwo) console.log('hide loading') console.log(moment(Date.now()).format('YYYY-MM-DD HH:mm:ss') + ' testAsync end') }, async testSync() { let that = this console.log(moment(Date.now()).format('YYYY-MM-DD HH:mm:ss') + ' testSync start') console.log('show loading') let resultOne = that.getValueOne(); let resultTwo = that.getValueTwo(); let results = await Promise.all([resultOne, resultTwo]) console.log(moment(Date.now()).format('YYYY-MM-DD HH:mm:ss') + results[0]) console.log(moment(Date.now()).format('YYYY-MM-DD HH:mm:ss') + results[1]) console.log('hide loading') console.log(moment(Date.now()).format('YYYY-MM-DD HH:mm:ss') + ' testSync end') }, getValueOne() { let that = this let startTime = Date.now() return new Promise (function(resolve, reject) { setTimeout(function() { let endTime = Date.now() resolve(' 请求成功 one ' + moment(endTime - startTime) + 'ms') }, 1000) }) }, getValueTwo() { let that = this let startTime = Date.now() return new Promise(function (resolve, reject) { setTimeout(function () { let endTime = Date.now() resolve(' 请求成功 two ' + moment(endTime - startTime) + 'ms') }, 3000) }) }, })