# Http请求
该插件适用于普遍的请求场景,支持post
、get
、put
和delete
,以及上传下载等请求,有如下特点:
- 基于
Promise
对象实现更简单的request
使用方式,支持请求和响应拦截 - 支持全局挂载
- 支持多个全局配置实例
- 支持自定义验证器
- 支持文件上传/下载
- 支持task 操作
- 支持自定义参数
- 支持多拦截器
- 对参数的处理比
uni.request
更强
# 平台差异说明
App | H5 | 微信小程序 | 支付宝小程序 | 百度小程序 | 头条小程序 | QQ小程序 |
---|---|---|---|---|---|---|
√ | √ | √ | √ | √ | √ | √ |
说明
此插件集成自优秀的开源请求库:luch-request (opens new window)。uView对其进行了简单封装以及说明,如有不全之处, 可参考luch-request (opens new window)官方文档。
# 基本使用
api.js
import { http } from 'uview-next'; http.middleware(config) http.request(config) http.get(url[, config]) http.upload(url[, config]) http.delete(url[, data[, config]]) http.head(url[, data[, config]]) http.post(url[, data[, config]]) http.put(url[, data[, config]]) http.connect(url[, data[, config]]) http.options(url[, data[, config]]) http.trace(url[, data[, config]])
✅ Copy success!
# 全局配置
可选的配置项有如下:
{ baseURL: '', header: {}, method: 'GET', dataType: 'json', // #ifndef MP-ALIPAY responseType: 'text', // #endif // 注:如果局部custom与全局custom有同名属性,则后面的属性会覆盖前面的属性,相当于Object.assign(全局,局部) custom: {}, // 全局自定义参数默认值 // #ifdef H5 || APP-PLUS || MP-ALIPAY || MP-WEIXIN timeout: 60000, // #endif // #ifdef APP-PLUS sslVerify: true, // #endif // #ifdef H5 // 跨域请求时是否携带凭证(cookies)仅H5支持(HBuilderX 2.6.15+) withCredentials: false, // #endif // #ifdef APP-PLUS firstIpv4: false, // DNS解析时优先使用ipv4 仅 App-Android 支持 (HBuilderX 2.8.0+) // #endif // 局部优先级高于全局,返回当前请求的task,options。请勿在此处修改options。非必填 // getTask: (task, options) => { // 相当于设置了请求超时时间500ms // setTimeout(() => { // task.abort() // }, 500) // }, // 全局自定义验证器。参数为statusCode 且必存在,不用判断空情况。 validateStatus: (statusCode) => { // statusCode 必存在。此处示例为全局默认配置 return statusCode >= 200 && statusCode < 300 } }
✅ Copy success!
可以通过http.setConfig()
方法进行全局配置,比如配置请求的全局域名baseUrl
:
import { http } from '@/uni_modules/uview-next'; http.setConfig((config) => { /* config 为默认全局配置*/ config.baseURL = `https://www.example.com`; /* 根域名 */ return config })
✅ Copy success!
# GET请求
需要注意的是,get
请求与post
请求略有不同,get
请求所有参数都在方法的第二个参数中,而post
请求的第二个参数为请求参数params
,而第三个参数才为配置项。
import { http } from '@/uni_modules/uview-next'; // 基本用法,注意:get请求的参数以及配置项都在第二个参数中 http.get('/user/login', {params: {userName: 'name', password: '123456'}}).then(res => { }).catch(err => { }) // 局部修改配置,局部配置优先级高于全局配置 http.get('/user/login', { params: {userName: 'name', password: '123456'}, /* 会加在url上 */ header: {}, /* 会与全局header合并,如有同名属性,局部覆盖全局 */ dataType: 'json', // 注:如果局部custom与全局custom有同名属性,则后面的属性会覆盖前面的属性,相当于Object.assign(全局,局部) custom: {auth: true}, // 可以加一些自定义参数,在拦截器等地方使用。比如这里我加了一个auth,可在拦截器里拿到,如果true就传token // #ifndef MP-ALIPAY responseType: 'text', // #endif // #ifdef H5 || APP-PLUS || MP-ALIPAY || MP-WEIXIN timeout: 60000, // H5(HBuilderX 2.9.9+)、APP(HBuilderX 2.9.9+)、微信小程序(2.10.0)、支付宝小程序 // #endif // #ifdef APP-PLUS sslVerify: true, // 验证 ssl 证书 仅5+App安卓端支持(HBuilderX 2.3.3+) // #endif // #ifdef APP-PLUS firstIpv4: false, // DNS解析时优先使用ipv4 仅 App-Android 支持 (HBuilderX 2.8.0+) // #endif // #ifdef H5 withCredentials: false, // 跨域请求时是否携带凭证(cookies)仅H5支持(HBuilderX 2.6.15+) // #endif // 返回当前请求的task, options。请勿在此处修改options。非必填 getTask: (task, options) => { // 相当于设置超时时间500ms // setTimeout(() => { // task.abort() // }, 500) }, //validateStatus: (statusCode) => { // statusCode 必存在。此处示例为全局默认配置。演示,非必填选项 // return statusCode >= 200 && statusCode < 300 //} }).then(res => { }).catch(err => { })
✅ Copy success!
# POST请求
需要注意的是,get请求与post请求略有不同,get请求所有参数都在方法的第二个参数中,而post请求的第二个参数为请求参数params,而第三个参数才为配置项。
import { http } from '@/uni_modules/uview-next'; // 基本用法,注意:post的第三个参数才为配置项 http.post('/user/login', {userName: 'name', password: '123456'} ).then(res => { }).catch(err => { }) // 局部修改配置,局部配置优先级高于全局配置 http.post('/user/login', {userName: 'name', password: '123456'}, { params: {}, /* 会加在url上 */ header: {}, /* 会与全局header合并,如有同名属性,局部覆盖全局 */ dataType: 'json', // 注:如果局部custom与全局custom有同名属性,则后面的属性会覆盖前面的属性,相当于Object.assign(全局,局部) custom: {auth: true}, // 可以加一些自定义参数,在拦截器等地方使用。比如这里我加了一个auth,可在拦截器里拿到,如果true就传token // #ifndef MP-ALIPAY responseType: 'text', // #endif // #ifdef H5 || APP-PLUS || MP-ALIPAY || MP-WEIXIN timeout: 60000, // H5(HBuilderX 2.9.9+)、APP(HBuilderX 2.9.9+)、微信小程序(2.10.0)、支付宝小程序 // #endif // #ifdef APP-PLUS sslVerify: true, // 验证 ssl 证书 仅5+App安卓端支持(HBuilderX 2.3.3+) // #endif // #ifdef APP-PLUS firstIpv4: false, // DNS解析时优先使用ipv4 仅 App-Android 支持 (HBuilderX 2.8.0+) // #endif // #ifdef H5 withCredentials: false, // 跨域请求时是否携带凭证(cookies)仅H5支持(HBuilderX 2.6.15+) // #endif // 返回当前请求的task, options。请勿在此处修改options。非必填 getTask: (task, options) => { // 相当于设置超时时间500ms // setTimeout(() => { // task.abort() // }, 500) }, //validateStatus: (statusCode) => { // statusCode 必存在。此处示例为全局默认配置。演示,非必填选项 // return statusCode >= 200 && statusCode < 300 //} }).then(res => { }).catch(err => { })
✅ Copy success!
# UPLOAD请求
具体参数说明:uni.uploadFile (opens new window)
import { http } from '@/uni_modules/uview-next'; http.upload('api/upload/img', { params: {}, /* 会加在url上 */ // #ifdef APP-PLUS || H5 files: [], // 需要上传的文件列表。使用 files 时,filePath 和 name 不生效。App、H5( 2.6.15+) // #endif // #ifdef MP-ALIPAY fileType: 'image/video/audio', // 仅支付宝小程序,且必填。 // #endif filePath: '', // 要上传文件资源的路径。 // 注:如果局部custom与全局custom有同名属性,则后面的属性会覆盖前面的属性,相当于Object.assign(全局,局部) custom: {auth: true}, // 可以加一些自定义参数,在拦截器等地方使用。比如这里我加了一个auth,可在拦截器里拿到,如果true就传token name: 'file', // 文件对应的 key , 开发者在服务器端通过这个 key 可以获取到文件二进制内容 // #ifdef H5 || APP-PLUS timeout: 60000, // H5(HBuilderX 2.9.9+)、APP(HBuilderX 2.9.9+) // #endif header: {}, /* 会与全局header合并,如有同名属性,局部覆盖全局 */ formData: {}, // HTTP 请求中其他额外的 form data // 返回当前请求的task, options。请勿在此处修改options。非必填 getTask: (task, options) => { // task.onProgressUpdate((res) => { // console.log('上传进度' + res.progress); // console.log('已经上传的数据长度' + res.totalBytesSent); // console.log('预期需要上传的数据总长度' + res.totalBytesExpectedToSend); // // // 测试条件,取消上传任务。 // if (res.progress > 50) { // uploadTask.abort(); // } // }); }, //validateStatus: (statusCode) => { // statusCode 必存在。此处示例为全局默认配置。演示,非必填选项 // return statusCode >= 200 && statusCode < 300 //} }).then(res => { // 返回的res.data 已经进行JSON.parse }).catch(err => { })
✅ Copy success!
# DOWNLOAD请求
具体参数说明:uni.downloadFile (opens new window)
import { http } from '@/uni_modules/uview-next'; http.download('api/download', { params: {}, /* 会加在url上 */ // #ifdef H5 || APP-PLUS timeout: 3000, // H5(HBuilderX 2.9.9+)、APP(HBuilderX 2.9.9+) // #endif header: {}, /* 会与全局header合并,如有同名属性,局部覆盖全局 */ custom: {}, // 自定义参数 // 返回当前请求的task, options。非必填 getTask: (task, options) => { // setTimeout(() => { // task.abort() // }, 500) }, //validateStatus: (statusCode) => { // statusCode 必存在。此处示例为全局默认配置。演示,非必填选项 // return statusCode >= 200 && statusCode < 300 //} }).then(res => { }).catch(err => { })
✅ Copy success!
# 请求拦截器
import { http } from '@/uni_modules/uview-next'; http.interceptors.request.use((config) => { // 可使用async await 做异步操作 config.header = { ...config.header, a: 1 // 演示拦截器header加参 } // 演示custom 用处 // if (config.custom.auth) { // config.header.token = 'token' // } // if (config.custom.loading) { // uni.showLoading() // } // 演示 // if (!token) { // 如果token不存在,return Promise.reject(config) 会取消本次请求 // return Promise.reject(config) // } return config }, config => { // 可使用async await 做异步操作 return Promise.reject(config) })
✅ Copy success!
# 响应拦截器
import { http } from '@/uni_modules/uview-next'; http.interceptors.response.use((response) => { /* 对响应成功做点什么 可使用async await 做异步操作*/ // if (response.data.code !== 200) { // 服务端返回的状态码不等于200,则reject() // return Promise.reject(response) // return Promise.reject 可使promise状态进入catch // if (response.config.custom.verification) { // 演示自定义参数的作用 // return response.data // } console.log(response) return response }, (response) => { /* 对响应错误做点什么 (statusCode !== 200)*/ console.log(response) return Promise.reject(response) })
✅ Copy success!
# 实践
假设我们项目中需要用到请求和响应拦截器,并且在请求拦截器中需要调用vuex
中的变量,可按如下步骤进行操作(仅供参考):
# 1. 全局配置,以及请求,响应拦截器定义
在/utils/request.js
中,写入如下内容:
request.js
import { http } from '@/uni_modules/uview-next'; // 仅示例,请根据实际情况调整 // import { useUserStore } from '@/stores/modules/user'; const request = () => { http.setConfig(config => { config.baseURL = 'https://www.example.com'; /* 根域名 */ return config; }); // 请求拦截 http.interceptors.request.use( config => { // 仅示例,请根据实际情况调整 // const { token } = useUserStore(); // if (token) config.header.token = token; return config; }, config => { return Promise.reject(config); } ); // 响应拦截 http.interceptors.response.use( ({ data }: { data: any }) => { return Promise.resolve(data); }, ({ statusCode, data, errMsg }: { statusCode: number; data: any; errMsg: string }) => { if(statusCode == 500){ uni.$u.toast('服务器错误,请稍后再试'); return new Promise(() => {}); }else{ return Promise.reject(); } } ); }; export default request;
✅ Copy success!
# 2. 引用配置
我们可以在main.js
中引用/utils/request.js
main.js
import { createSSRApp } from 'vue'; import App from './App.vue'; import uviewPlus from '@/uni_modules/uview-plus'; import request from '@/utils/request'; export function createApp() { const app = createSSRApp(App); app.use(uviewPlus); app.use(request); return { app }; }
✅ Copy success!
# 3. Api集中管理
在/api/user.js
中编写请求接口:
user.js
import { http } from '@/uni_modules/uview-next'; // 手机号登录 export const apiLogin = (params: any) => http.post('/weapp/login', params); // 退出登录 export const apiLogout = () => http.post('/weapp/login/logout'); // 获取用户信息 export const apiUserProfile = (params: any) => http.get('/weapp/user/profile', params); // 更新用户信息 export const apiUserUpdate = (params: any) => http.post('/weapp/user/update', params);
✅ Copy success!
# 4. 发送请求
import { apiUserProfile } from '/api/user.js'; //获取用户信息 const getUserProfile = async ()=> { const res = await apiUserProfile(); console.log(res) }
✅ Copy success!