第三章:微信小程序开发常用的API介绍及使用 (17讲)
50 | 网络接口简介(一):如何使用wx.request接口
51 | 网络接口简介(二):将登陆代码模块化封装
52 | 网络接口简介(三):Promise介绍及 6 个常用方法
53 | 网络接口简介(四):Promise三个方法any、all与race的使用介绍
54 | 网络接口简介(五):基于Promise+await、async关键字改写登录模块
55 | 网络接口简介(六):关于Page页面隐藏代码执行及Promise对象的catch处理的补充
- 以下是封装的请求方法,可以用
.then().catch或awsit,async
import toast from "./vantToast";
import ls from "./localStorage";
import {filterObj} from "./others";
const getHeader = (method) => {
let header = {
'Authorization': ls.get('token'),
'AuthorizationType': 'plat'
}
if (method === 'POST') {
header['content-type'] = 'application/x-www-form-urlencoded';
} else if (method === 'POST_JSON') {
header['content-type'] = 'application/json;charset=UTF-8';
}
return header
}
const getMethod = (method) => {
if (method === "POST_JSON") {
return "POST";
}
return method;
}
const FnThen = (res, returnMsg) => {
return new Promise((resolve, reject) => {
const resCode = {
"A0230": "用户登陆已过期",
"A0301": "访问未授权",
"A0302": "正在授权中",
"A0303": "用户授权申请被拒绝",
"A0310": "因访问对象隐私设置被拦截",
"A0311": "授权已过期",
"A0312": "无权限使用 API",
"A0320": "用户访问被拦截",
};
const {data, msg = '', code = '200'} = res;
if (code === "00000") {
const resData = returnMsg ? {data, msg} : data;
resolve(resData);
} else {
toast.info(msg).then(() => {
if (Object.keys(resCode).includes(code)) {
ls.clear();
// wx.redirectTo({url: '/pages/login/index'});
}
});
reject(null);
}
})
};
const FnCatch = (error) => {
return new Promise((resolve, reject) => {
if (error) {
toast.info('请求错误');
}
reject(error);
})
};
export const httpAction = (
{
url = "",
data = {},
method = "GET",
returnMsg = false
}
) => {
return new Promise(
(resolve, reject) => {
wx.showLoading({
mask: true,
title: '加载中',
})
wx.request({
url: url,
data: filterObj(data),
header: getHeader(method),
method: getMethod(method),
success(res) {
if (res.statusCode === 200) {
resolve(res.data);
} else {
reject(res);
}
},
fail(res) {
reject(res);
},
complete() {
wx.hideLoading()
}
})
})
.then(res => FnThen(res, returnMsg))
.catch(error => FnCatch(error))
};
export const getAction = ({url, data, returnMsg}) => {
return httpAction({url, data, method: "GET", returnMsg});
};
export const postAction = ({url, data, returnMsg}) => {
return httpAction({url, data, method: "POST", returnMsg});
};
export const postJsonAction = ({url, data, returnMsg}) => {
return httpAction({url, data, method: "POST_JSON", returnMsg});
};
API Promise化
扩展微信小程序api支持promise
安装
npm install --save miniprogram-api-promise
使用
在小程序入口(app.js)调用一次promisifyAll,只需要调用一次。
示例:
import { promisifyAll, promisify } from 'miniprogram-api-promise';
const wxp = {}
// promisify all wx's api
promisifyAll(wx, wxp)
console.log(wxp.getSystemInfoSync())
wxp.getSystemInfo().then(console.log)
wxp.showModal().then(wxp.openSetting())
// compatible usage
wxp.getSystemInfo({success(res) {console.log(res)}})
// promisify single api
promisify(wx.getSystemInfo)().then(console.log)
56 | 网络接口简介(七):学习EventChannel对象
EventChannel
基础库 2.7.3 开始支持,低版本需做兼容处理。
页面间事件通信通道
方法
-
EventChannel.emit(string eventName, any args)
触发一个事件
-
EventChannel.on(string eventName, EventCallback fn)
持续监听一个事件
-
EventChannel.once(string eventName, EventCallback fn)
监听一个事件一次,触发后失效
-
EventChannel.off(string eventName, EventCallback fn)
取消监听一个事件。给出第二个参数时,只取消给出的监听函数,否则取消所有监听函数
wx.navigateTo({
url: 'test?id=1',
events: {
// 为指定事件添加一个监听器,获取被打开页面传送到当前页面的数据
acceptDataFromOpenedPage: function(data) {
console.log(data)
},
someEvent: function(data) {
console.log(data)
}
...
},
success: function(res) {
// 通过eventChannel向被打开页面传送数据
res.eventChannel.emit('acceptDataFromOpenerPage', { data: 'test' })
}
})
//test.js
Page({
onLoad: function(option){
console.log(option.query)
const eventChannel = this.getOpenerEventChannel()
eventChannel.emit('acceptDataFromOpenedPage', {data: 'test'});
eventChannel.emit('someEvent', {data: 'test'});
// 监听acceptDataFromOpenerPage事件,获取上一页面通过eventChannel传送到当前页面的数据
eventChannel.on('acceptDataFromOpenerPage', function(data) {
console.log(data)
})
}
})
57 | 网络接口简介(八):观察者模式介绍及Event模块实现
-
mitt(与vue3框架使用相同)
//bus.js import mitt from "./mitt"; const emitter = mitt() const bus = {} bus.$on = emitter.on; bus.$off = emitter.off; bus.$emit = emitter.emit; bus.$all = emitter.all; export default bus;
58 | 网络接口简介(九):扩展wxp模块的request3方法,实现用户登录的自动融合
59 | tabBar组件(一):系统默认的tabBar组件如何开启及使用
"tabBar": {
"list": [
{
"pagePath": "pages/index/index",
"text": "首页",
"iconPath": "static/images/tabbar/icon1.png",
"selectedIconPath": "static/images/tabbar/icon1_1.png"
},
{
"pagePath": "pages/ucenter/index",
"text": "我的",
"iconPath": "static/images/tabbar/icon4.png",
"selectedIconPath": "static/images/tabbar/icon4_1.png"
}
]
},
具体见 tabbar
60 | tabBar组件(二):基于系统提供的自定义方式,实现一个tabBar组件
61 | tabBar组件(三):通过自定义组件扩展的方式,给任意组件添加通用方法
62 | 开放接口(一):如何对Page进行全局扩展
//extend-page.js
const extendPage = Page => {
return object => {
// 登录面板开头
if (!object.data) object.data = {}
object.data.showLoginPanel = false
// method
object.hi = function(name){
console.log(`hi ${name}`);
}
// 派发一个等待处理,需要有代码处理的事件
// 但这个方法没有什么用
object.triggerWaitingEvent = function (type, data = {}){
return new Promise((resolve,reject)=>{
let eventCallback = res => resolve(res)
Object.assign(data, {
eventCallback
})
this.triggerEvent(type, data)
})
}
return Page(object)
}
}
const originalPage = Page
Page = extendPage(originalPage)
//app.js
require("./lib/extend-page")
63 | 开放接口(二):优化前后端登录代码,解决后端解密错误
64 | 设备能力:如何实现扫码连WiFi功能?
async function connectWifi() {
let ssid = '201',
pass = '123456789'
let sysInfo = wx.getSystemInfoSync()
let platform = sysInfo.platform
// devtools/android/ios
// ios:iOS 10.0.1
console.log("platform", platform, sysInfo.system);
// 只有ios 11以上,及andoird 6以上,才有这样的wifi连接功能
if (platform == "android") {
let sysVersion = parseInt(sysInfo.system.substr(8))
if (sysVersion < 6) {
return "android版本低"
}
let res0 = await wx.wxp.getSetting({
withSubscriptions: false,
}).catch(err => {
console.log("err", err);
return `运行错误:${err}`
})
if (res0 && !res0.authSetting["scope.userLocation"]) {
// 如果没有这个权限,先授权
let authRes = await wx.wxp.authorize({
scope: 'scope.userLocation'
}).catch(err => {
console.log("err", err);
return `运行错误:${err}`
})
if (authRes && authRes.errMsg != "authorize:ok") {
console.log('地理授权失败', authRes.errMsg);
return 'android地理授权失败'
}
}
} else if (platform == "ios") {
let sysVersion = parseInt(sysInfo.system.substr(4))
if (sysVersion < 11) {
return "ios版本低"
}
await wx.wxp.showModal({
title: '请切到系统设置->wifi列表,等待wifi连接成功',
showCancel: false
}).catch(err => {
console.log("err", err);
return `运行错误:${err}`
})
} else {
return "平台不支持"
}
await wx.wxp.startWifi().catch(err => {
console.log("err", err);
return `运行错误:${err}`
})
await wx.wxp.getWifiList().catch(err => {
console.log("err", err);
return `运行错误:${err}`
})
let res = await new Promise((resolve, reject) => {
wx.onGetWifiList(res => {
resolve(res)
})
})
if (!res.wifiList.length) return "wifi列表为空"
console.log("res.wifiList", res.wifiList);
// var signalStrength = 0;
var bssid = '';
for (var i = 0; i < res.wifiList.length; i++) {
let wifi = res.wifiList[i]
if (wifi.SSID == ssid) {
bssid = wifi.BSSID
break
}
}
if (!bssid) return '未查询到目标wifi'
let res1 = await wx.wxp.connectWifi({
SSID: ssid,
BSSID: bssid,
password: pass
}).catch(err => {
console.log("err", err);
return `运行错误:${err}`
})
if (res1) {
console.log("wifi连接成功");
return "connectWifi:ok"
}
return "未知错误"
}
export default connectWifi