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' });
}
}