第三章:微信小程序开发常用的API介绍及使用 (17讲)

518 阅读4分钟

第三章:微信小程序开发常用的API介绍及使用 (17讲)

50 | 网络接口简介(一):如何使用wx.request接口

51 | 网络接口简介(二):将登陆代码模块化封装

52 | 网络接口简介(三):Promise介绍及 6 个常用方法

53 | 网络接口简介(四):Promise三个方法any、all与race的使用介绍

54 | 网络接口简介(五):基于Promise+await、async关键字改写登录模块

55 | 网络接口简介(六):关于Page页面隐藏代码执行及Promise对象的catch处理的补充

  • 以下是封装的请求方法,可以用.then().catchawsit,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 开始支持,低版本需做兼容处理

页面间事件通信通道

方法

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组件

拓展组件-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

65 | 前期留言集中答疑(一)

66 | 前期留言集中答疑(二)