config.js文件是这样的
interface Config {
  baseUrl: string;
}
const config: Config = {
  baseUrl: 'http://qu.test/api/weapp'
};
export default config;
我们可以将api列表封装在api.js文件中,代码如下:
// api.ts
import Request from './request';
const request = new Request();
export const communitiesApi = {
  // 获取附近小区
  searchNearby: (data?:any) => request.get(`/communities/searchNearby`, data),
  // 获取小区详情,id可以不传递
  show: (id: number | string) => request.get(`/communities/${id}`),
  // 新增产品
  create: (data: any) => request.post(`/products`, data),
  // 修改产品
  update: (id: number | string, data: any) => request.put(`/products/${id}`, data),
  // 删除产品
  delete: (id: number | string) => request.delete(`/products/${id}`)
};
export const userApi = {
  //当前用户信息
  me: () => request.get(`/user`),
  // 用户登录
  // login: (data: any) => request.post(`/login`, data, { noToken: true }),
  // 更新当前用户信息
  update: (data: any) => request.put(`/user`, data),
  // 上传头像
  uploadAvatar: (filePath: string) => {
    const name = 'avatar';
    const formData = {};
    return request.uploadFile({ url: '/user/avatar', filePath, name, formData });
  }
};
完整的request.js文件代码如下:
//request.ts
import config from './config';
interface RequestOptions {
  baseUrl?: string;
  url: string;
  data?: any;
  header?: any;
  method?: string;
  noToken?: boolean;
}
class Request {
  private config = {
    baseUrl: config.baseUrl,
    header: {
      'Content-Type': 'application/json',
      'X-Requested-With': 'XMLHttpRequest'
    },
    method: 'GET',
    noToken: false
  };
  public async wxLogin() {
    console.log('第四步:调用微信登录接口,获取code')
    try {
      console.log('第四步:调用微信登录接口,获取code')
      // 调用微信登录接口,获取code
      const { code } =  await wx.login();
      const systemInfo = wx.getSystemInfoSync();
      const device_name = systemInfo.model;
      // 使用 wx.request() 方法获取 token,而不是之前的 request() 方法
      const url = this.config.baseUrl + '/authorizations';
      const data = { code, device_name };
      const header = Object.assign({}, this.config.header, {
        Authorization: '',
      });
      console.log('第四步:获取token', url, data, header)
      // 将 wx.request 方法封装成一个 Promise 对象
      await new Promise((resolve, reject) => {
        wx.request({
          url,
          data,
          header,
          method: 'POST',
          success: (res) => {
            console.log( res.data);
            console.log('第五步:获取token', res.data.token);
            // 将 token 以及根据 expire_in 计算的过期时间 expiredTime 存入缓存
            wx.removeStorageSync('token');
            wx.removeStorageSync('expiredTime');
            wx.setStorageSync('token', res.data.token);
            wx.setStorageSync('expiredTime', new Date().getTime() + res.data.expire_in * 1000 * 60);
            resolve(res);
          },
          fail: (err) => {
            console.log('第四步报错', err);
            reject(err);
          },
        });
      });
    } catch (e) {
      console.log('第四步报错', e);
      throw e;
    }
  }
  public async request(options: RequestOptions): Promise<any> {
    console.log('第一步:发起请求', options.url)
    const { options: processedOptions, header } = await this.processOptions(options);
    // 请求的url
    const url = processedOptions.baseUrl + processedOptions.url;
    console.log(url)
    // 请求的参数
    const data = processedOptions.data;
    // 请求的header
    const processedHeader = header;
    // 请求的方法
    const method = processedOptions.method;
    // 返回一个Promise对象
    return new Promise((resolve, reject) => {
      console.log('第七步:发起请求', url, data, processedHeader, method)
      wx.request({
        url,
        data,
        header: processedHeader,
        method: method as 'GET' | 'POST' | 'PUT' | 'DELETE' | 'OPTIONS' | 'HEAD' | 'TRACE' | 'CONNECT',
        success: (res) => {
          // 请求成功,如果响应中有错误信息,则拒绝Promise
          if (typeof res.data === 'string') {
            reject(new Error(res.data));
          } else {
            const data = typeof res.data === 'object' ? res.data : JSON.parse(res.data);
            if (data.status === 'error') {
              reject(new Error(data.message));
            } else {
              resolve(res);
            }
          }
        },
        fail: (err) => {
          // 请求失败,拒绝Promise
          reject(err);
        }
      });
    });
  }
  public async uploadFile(options: wx.UploadFileOptions): Promise<any> {
    const { options: processedOptions, header } = await this.processOptions(options);
    // 请求的文件路径
    const filePath = processedOptions.filePath;
    // 请求的文件名
    const name = processedOptions.name;
    // 请求的formData
    const formData = processedOptions.formData;
    // 返回一个Promise对象
    return new Promise((resolve, reject) => {
      wx.uploadFile({
        url: processedOptions.baseUrl + processedOptions.url,
        filePath,
        name,
        formData,
        header,
        success: (res) => {
          // 请求成功,如果响应中有错误信息,则拒绝Promise
          const data = JSON.parse(res.data);
          resolve(data);
        },
        fail: (err) => {
          // 请求失败,拒绝Promise
          reject(err);
        }
      });
    });
  }
  private async processOptions(options: RequestOptions | wx.UploadFileOptions): Promise<{ options: RequestOptions | wx.UploadFileOptions, header: any }> {
    // 获取缓存中的token
    let token = wx.getStorageSync('token');
    console.log('第二步:判断缓存是否过期', (!token || this.isTokenExpired(token)))
    // 判断token是否存在或是否过期
    if (!token || this.isTokenExpired(token)) {
      console.log('第三步:调用wxLogin方法重新获取token')
      // 如果token不存在或已过期,则调用wxLogin方法重新获取token
      await this.wxLogin();
      // 重新获取token
      token = wx.getStorageSync('token')
      console.log('第六步:拿到token', token)
    }
    // 如果options中指定了不需要token,则不设置token
    if (options.noToken) {
      options.header = options.header || {};
    } else {
      // 如果token存在,则在请求的header中设置token
      if (token) {
        options.header = options.header || {};
        options.header.Authorization = `Bearer ${token}`;
      }
    }
    // 合并用户传入的配置和默认配置
    const processedOptions = Object.assign({}, this.config, options);
    return { options: processedOptions, header: processedOptions.header };
  }
  private isTokenExpired(token: string): boolean {
    // 获取缓存中存储的 token 的过期时间
    const expiredTime = wx.getStorageSync('expiredTime');
    // 如果 expiredTime 不存在,则说明 token 不存在或已过期
    if (!expiredTime) {
      return true;
    }
    // 如果当前时间已经大于 expiredTime,则说明 token 已过期
    if (new Date().getTime() > expiredTime) {
      return true;
    }
    // 如果执行到这里,说明 token 未过期
    return false;
  }
  public get(url: string, data?: any): Promise<any> {
    return this.request({ url, data });
  }
  public post(url: string, data?: any): Promise<any> {
    return this.request({ url, data, method: 'POST' });
  }
  public put(url: string, data?: any): Promise<any> {
    return this.request({ url, data, method: 'PUT' });
  }
  public delete(url: string, data?: any): Promise<any> {
    return this.request({ url, data, method: 'DELETE' });
  }
}
export default Request;
在另一个页面中,您可以这样使用封装的API请求:
// 调用api接口
import { productApi, userApi } from './api';
// 获取产品列表,不携带token
const productList = await productApi.list();
console.log(productList);
// 新增产品,携带token
const addProduct = await productApi.create({ name: 'product1' });
console.log(addProduct);
// 修改产品,携带token
const updateProduct = await productApi.update(1, { name: 'product2' });
console.log(updateProduct);
// 删除产品,携带token
const deleteProduct = await productApi.delete(1);
console.log(deleteProduct);
// 用户登录,不携带token
const login = await userApi.login({ username: 'test', password: '123456' });
console.log(login);
// 获取用户信息,携带token
const userInfo = await userApi.userInfo();
console.log(userInfo);
// ...
// 调用其他模块的api接口
也可以根据状态码判断执行内容
const productList = await productApi.list();
if (productList.code === 200001) {
  // 执行下一步操作
} else {
  // 执行其他操作
}
上传头像,可以这样使用
import { userApi } from './api';
  async onChooseAvatar(e) {
    const { avatarUrl } = e.detail
    try {
      const response = await userApi.uploadAvatar(avatarUrl);
      if (response.code === 200001) {
        response.data.avatar = avatarUrl;
        this.setData({
          me: response.data,
        });
        wx.setStorageSync('me', response.data);
      }
      wx.showToast({ title: '上传成功' });
    } catch (e) {
      console.error(e);
      wx.showToast({ title: '上传失败', icon: 'none' });
    }
  }