Table of Contents
用 promise 封装 wx.request
在使用小程序请求的过程中我们会用到小程序的 wx.request 接口,但 wx.request 还是基于 callback 封装的,es6 出现后大家更习惯于使用 promise 形式的请求,所以这里我们使用 promise 简单封装一下。
封装需要实现的核心功能:
- 使用 ES6 Promise;
- 可以配置 baseUrl;
- 可以拦截请求参数;
- 可以拦截响应数据;
封装的请求
// 目录(/utils/api/index.js)
/** * 封装的请求函数 * @param {object} options wx.request配置对象 * @param {string} config.baseUrl 接口基础地址 * @param {() => ({header: object; data: (data:any) => any})} config.interceptorRequest 请求拦截器函数,对data的处理函数需要返回处理后的数据 * @param {(res: {cookie: string[], data: object, errMsg: string, header: object, statusCode: number}) => any} config.interceptorResponse 响应拦截器函数,需要返回处理后的响应数据 */module.exports = function api(options, config) { return new Promise((resolve, reject) => { wx.request({ ...options, header: { ...options.header, ...(config && config.interceptorRequest ? config.interceptorRequest().header : {}), }, data: config && config.interceptorRequest && config.interceptorRequest().data ? interceptorRequest.data(options.data) : options.data, url: `${config && config.baseUrl ? config.baseUrl : ""}${options.url}`, success: (res) => { const resData = config && config.interceptorResponse ? config.interceptorResponse(res) : res; resolve(resData); }, fail: (err) => { reject(err); }, }); });};新建请求实例
// 目录(/api/index.js)
const api = require("/utils/request/index");
// 接口基础地址const fooUrl = "https://your-backend-service.com/foo/";const barUrl = "https://your-another-backend-service.com/bar/";
// 请求拦截器const interceptorRequest = () => { return { header: { // 从存储中拿取cookie,假设登录时已存入 cookie: wx.getStorageSync("cookie") || "", // 其他自定义头 enterprise: "my-enterprise", }, };};
// 响应拦截器const interceptorResponse = (res) => { console.log(res); // 若服务器响应为200,且后端服务响应也为200或后端服务响应不存在code(文件请求的响应为二进制流,无code码),视为正常请求,直接返回请求 if (res.statusCode === 200 && (!res.data.code || res.data.code === 200)) { return res; } // 若服务器响应为200,且后端服务响应为401,说明用户未登录或登录过期,弹窗提示并reject返回值,在2秒后清空存储中的用户数据,退出登录并跳转至登录页 else if (res.statusCode === 200 && res.data.code === 401) { wx.showToast({ title: res.data && res.data.msg ? res.data.msg : "登录过期", icon: "none", }); setTimeout(() => { wx.clearStorage(); wx.reLaunch({ url: "/pages/login/login", }); }, 2000); return Promise.reject(res); } // 其他情况皆视为请求出错,弹窗提示并reject返回值 else { wx.showToast({ title: res.data && res.data.msg ? res.data.msg : "请求失败", icon: "none", }); return Promise.reject(res); }};
// 不同后端服务对应的不同请求实例const apiFoo = (options) => api(options, { baseUrl: fooUrl, interceptorRequest, interceptorResponse });const apiBar = (options) => api(options, { baseUrl: barUrl, interceptorRequest, interceptorResponse });
module.exports = { apiFoo, apiBar };创建接口
// 目录(/api/foo/index.js)
const { apiFoo } = require("/api/index");
const getFooData = () => apiFoo({ url: `/foo-data`, });
const postFooDataUpdate = (data) => apiFoo({ url: `/foo-data/update`, data, method: "POST", });
const getFooDataDelete = (data) => apiFoo({ url: `/foo-data/delete/${data.id}`, });
module.exports = { getFooData, postFooDataUpdate, getFooDataDelete,};使用接口
// 目录(/pages/foo/foo.js)
const { getFooData, getFooDataDelete } = require("/api/foo/index");
Page({ // async await式 用法 async tapDelete(event) { wx.showLoading(); try { const deleteId = await getFooDataDelete({ id: event.detail.id }); console.log("deleted foo data id", deleteId); // 执行其他代码逻辑 } catch (err) { console.error(err); } finally { wx.hideLoading(); } }, // promise式 用法 onLoad() { getFooData() .then((res) => { console.log("foo data response", res); // 执行其他代码逻辑 }) .catch(console.err); },});