uni-app之网络请求
一,介绍
uni.request(OBJECT),发起网络请求,以下主要是一些特殊的参数说明,详细的可查看uni-app官网。
1,method的有效值必须是大写,默认GET方式;
2,success 返回参数说明
参数 | 类型 | 说明 |
---|---|---|
data | Object/String/ArrayBuffer | 开发者服务器返回的数据 |
statusCode | Number | 开发者服务器返回的 HTTP 状态码 |
header | Object | 开发者服务器返回的 HTTP Response Header |
3,传参数据说明
最终发送给服务器的数据是 String 类型,如果传入的 data 不是 String 类型,会被转换成 String。转换规则如下:
-
- 对于
GET
方法,会将数据转换为 query string。例如{ name: 'name', age: 18 }
转换后的结果是name=name&age=18
。 - 对于
POST
方法且header['content-type']
为application/json
的数据,会进行 JSON 序列化。 - 对于
POST
方法且header['content-type']
为application/x-www-form-urlencoded
的数据,会将数据转换为 query string。
- 对于
二,网络请求封装
第一步:参数统一初始化配置
1 import { configBaseUrl, GET } from "./const"
1 config: { 2 baseUrl: configBaseUrl, 3 header: { 4 'Content-Type': 'application/json;charset=UTF-8', 5 }, 6 data: {}, 7 method: GET, 8 dataType: "json", /* 如设为json,会对返回的数据做一次 JSON.parse */ 9 responseType: "text", 10 success() { }, 11 fail() { }, 12 complete() { } 13 },
第二步:拦截器定义
1 interceptor: { 2 request: null, 3 response: null 4 },
第三步:处理传入的参数
1 options.baseUrl = options.baseUrl || this.config.baseUrl 2 options.dataType = options.dataType || this.config.dataType 3 options.url = options.baseUrl + options.url 4 options.data = options.data || {} 5 options.method = options.method.toUpperCase() || this.config.method 6 7 // 请求头部类型提供自定义 8 const contentType = options.contentType; 9 delete options.contentType;// // 'Content-Type': 'application/x-www-form-urlencoded' 10 const headers = contentType ? { 'Content-Type': contentType } : this.config.baseUrl; //默认 application/json;charset=UTF-8 json数据传参 11 options.header = Object.assign({}, options.header, headers);
第四步:发送网络请求
使用Promise方法,方便调用获取返回的参数;并做统一的处理以及日志记录。
1 return new Promise((resolve, reject) => { 2 let _config: any = null 3 4 options.complete = (response: any) => { 5 let statusCode = response.statusCode 6 response.config = _config 7 if (process.env.NODE_ENV === 'development') { 8 if (statusCode === 200) { 9 console.log("【" + _config.requestId + "】 结果:" + JSON.stringify(response.data)) 10 } 11 } 12 if (this.interceptor.response) { 13 // @ts-ignore 14 let newResponse = this.interceptor.response(response) 15 if (newResponse) { 16 response = newResponse 17 } 18 } 19 // 统一的响应日志记录 20 _reslog(response) 21 if (statusCode === 200) { //成功 22 const result = _getResult(response.data);//网络请求成功后数据处理 23 resolve(result); 24 } else { 25 reject(response) 26 } 27 } 28 29 _config = Object.assign({}, this.config, options) 30 _config.requestId = new Date().getTime() 31 32 if (this.interceptor.request) { 33 // @ts-ignore 34 this.interceptor.request(_config) 35 } 36 37 // 统一的请求日志记录 38 _reqlog(_config) 39 uni.request(_config); 40 });
第五步:再次封装,习惯使用
扫描二维码关注公众号,回复:
8125720 查看本文章
1 /** 2 * 服务统一处理 添加拦截器 并抛出使用 3 */ 4 function requestApi(url: String, options: any) { 5 if (!options) { 6 options = {} 7 } 8 /** 9 * @description: 响应拦截器 10 * @param {object} 当前请求成功回调数据 11 * @return 不return对象,则不返回数据 12 */ 13 // @ts-ignore 14 httpService.interceptor.response = (response: any) => { 15 console.log('个性化response....', JSON.stringify(response)) 16 //判断返回状态 执行相应操作 17 return response; 18 } 19 /** 20 * @description: 请求拦截器 21 * @param {object} 当前请求配置参数 22 * @return 不return对象,则不发送当前请求 23 */ 24 // @ts-ignore 25 httpService.interceptor.request = (config: any) => { 26 console.log('config....', JSON.stringify(config)) 27 //获取配置信息 统一添加配置与判断 28 return config; 29 } 30 options.url = url 31 return httpService.request(options); 32 }
第六步:完整代码
1 import { configBaseUrl, GET } from "./const"; 2 3 const httpService = { 4 config: { 5 baseUrl: configBaseUrl, 6 header: { 7 'Content-Type': 'application/json;charset=UTF-8', 8 }, 9 data: {}, 10 method: GET, 11 dataType: "json", /* 如设为json,会对返回的数据做一次 JSON.parse */ 12 responseType: "text", 13 success() { }, 14 fail() { }, 15 complete() { } 16 }, 17 interceptor: { 18 request: null, 19 response: null 20 }, 21 request(options: any) { 22 if (!options) { 23 options = {} 24 } 25 options.baseUrl = options.baseUrl || this.config.baseUrl 26 options.dataType = options.dataType || this.config.dataType 27 options.url = options.baseUrl + options.url 28 options.data = options.data || {} 29 options.method = options.method.toUpperCase() || this.config.method 30 31 // 请求头部类型提供自定义 32 const contentType = options.contentType; 33 delete options.contentType;// // 'Content-Type': 'application/x-www-form-urlencoded' 34 const headers = contentType ? { 'Content-Type': contentType } : this.config.baseUrl; //默认 application/json;charset=UTF-8 json数据传参 35 options.header = Object.assign({}, options.header, headers); 36 // 加密数据 37 38 // 数据签名 39 /* 40 _token = {'token': getStorage(STOREKEY_LOGIN).token || 'undefined'}, 41 _sign = {'sign': sign(JSON.stringify(options.data))} 42 options.header = Object.assign({}, options.header, _token,_sign) 43 */ 44 45 return new Promise((resolve, reject) => { 46 let _config: any = null 47 48 options.complete = (response: any) => { 49 let statusCode = response.statusCode 50 response.config = _config 51 if (process.env.NODE_ENV === 'development') { 52 if (statusCode === 200) { 53 console.log("【" + _config.requestId + "】 结果:" + JSON.stringify(response.data)) 54 } 55 } 56 if (this.interceptor.response) { 57 // @ts-ignore 58 let newResponse = this.interceptor.response(response) 59 if (newResponse) { 60 response = newResponse 61 } 62 } 63 // 统一的响应日志记录 64 _reslog(response) 65 if (statusCode === 200) { //成功 66 const result = _getResult(response.data);//网络请求成功后数据处理 67 resolve(result); 68 } else { 69 reject(response) 70 } 71 } 72 73 _config = Object.assign({}, this.config, options) 74 _config.requestId = new Date().getTime() 75 76 if (this.interceptor.request) { 77 // @ts-ignore 78 this.interceptor.request(_config) 79 } 80 81 // 统一的请求日志记录 82 _reqlog(_config) 83 uni.request(_config); 84 }); 85 }, 86 } 87 88 /** 89 * 服务统一处理 添加拦截器 并抛出使用 90 */ 91 function requestApi(url: String, options: any) { 92 if (!options) { 93 options = {} 94 } 95 /** 96 * @description: 响应拦截器 97 * @param {object} 当前请求成功回调数据 98 * @return 不return对象,则不返回数据 99 */ 100 // @ts-ignore 101 httpService.interceptor.response = (response: any) => { 102 console.log('个性化response....', JSON.stringify(response)) 103 //判断返回状态 执行相应操作 104 return response; 105 } 106 /** 107 * @description: 请求拦截器 108 * @param {object} 当前请求配置参数 109 * @return 不return对象,则不发送当前请求 110 */ 111 // @ts-ignore 112 httpService.interceptor.request = (config: any) => { 113 console.log('config....', JSON.stringify(config)) 114 //获取配置信息 统一添加配置 115 return config; 116 } 117 options.url = url 118 return httpService.request(options); 119 } 120 121 /** 122 * 请求接口日志记录 123 */ 124 function _reqlog(req: any) { 125 if (process.env.NODE_ENV === 'development') { 126 console.log("【" + req.requestId + "】 地址:" + req.url) 127 if (req.data) { 128 console.log("【" + req.requestId + "】 请求参数:" + JSON.stringify(req.data)) 129 } 130 } 131 // 调接口异步写入日志数据库 132 } 133 134 /** 135 * 响应接口日志记录 136 */ 137 function _reslog(res: any) { 138 let _statusCode = res.statusCode; 139 if (process.env.NODE_ENV === 'development') { 140 console.log("【" + res.config.requestId + "】 地址:" + res.config.url) 141 if (res.config.data) { 142 console.log("【" + res.config.requestId + "】 请求参数:" + JSON.stringify(res.config.data)) 143 } 144 console.log("【" + res.config.requestId + "】 响应结果:" + JSON.stringify(res)) 145 } 146 147 // 除了接口服务错误外,其他日志调接口异步写入日志数据库 148 switch (_statusCode) { 149 case 200: 150 break; 151 case 401: 152 break; 153 case 404: 154 ToastWarn('找不了资源文件!') 155 break; 156 default: 157 ToastWarn('服务器异常!') 158 break; 159 } 160 } 161 162 /** 163 * 结果统一处理 164 */ 165 function _getResult(res: any) { 166 if (res.httpCode === 200) { 167 return { result: res.data }; 168 } 169 } 170 171 export default requestApi;
三,使用封装方法(vue项目皆可按如下封装调用)
3.1,store中调用
第一步:引入接口
1 import { login } from '../../services/api/user'
第二步:在store中使用
1 login({ commit }, userInfo) {//store actions中的方法 2 const { username, password } = userInfo 3 return new Promise((resolve, reject) => { 4 login({ username: username.trim(), password: password }).then(response => {//登录接口 5 const { result } = response 6 console.log('result===', result) 7 resolve(result) 8 }).catch(error => { 9 reject(error) 10 }) 11 }) 12 }
第三步:在页面中调用actions方法
1 this.$store.dispatch('user/login', { username: this.username, password: this.password }) 2 .then(() => { 3 ToastSuccess('登陆成功'); 4 uni.switchTab({ 5 url: '../index/index', 6 }) 7 }).catch(() => { 8 ToastWarn('登陆失败'); 9 });
3.2,封装统一的api入口
第一步:封装接口服务统一入口
在services中添加文件index.ts,添加如下代码
1 // https://webpack.js.org/guides/dependency-management/#requirecontext 2 const apisFiles = require.context('./api', false, /\.ts$/); 3 4 // you do not need `import user from './api/user'` 5 // it will auto require all api from api file 6 const apis = apisFiles.keys().reduce((apis, apiPath) => { 7 // set './user.ts' => 'user' 8 // const moduleName = apiPath.replace(/^\.\/(.*)\.\w+$/, '$1');//文件名 9 const value = apisFiles(apiPath); 10 apis = Object.assign({}, apis, value);//将所有可枚举属性的值从一个或多个源对象复制到目标对象。它将返回目标对象。 11 return apis; 12 }, {}); 13 14 export default { 15 ...apis, 16 }
第二步:使用接口服务
添加api文件夹,并添加ts文件,名字可随意命名
1 import requestApi from '@/utils/request'; 2 import { POST } from '@/utils/const'; 3 4 /* 5 ***登录*** 6 */ 7 export function login(data: any) { 8 return requestApi('/api/v1/yingqi/user/login', { 9 method: POST, 10 data: { 11 loginCode: data.username, 12 password: data.password 13 }, 14 }); 15 }
第三步:统一接口入口
在main.js添加如下代码即可
1 import servicesApi from '@/services'; 2 Vue.prototype.$servicesApi = servicesApi
第四步:页面中使用
1 this.$servicesApi.getSingleDataById().then((response: any) => { 2 const { result } = response 3 console.log('result===', result) 4 }).catch((error: any) => { 5 console.log('error===', error) 6 })
其他参数配置文件
export const GET: String = 'GET'; export const POST: String = 'POST'; export const PUT: String = 'PUT'; export const PATCH: String = 'PATCH'; export const DELETE: String = 'DELETE'; export const UPDATE: String = 'UPDATE'; //************************************************【 请求基础路径 】************************************************* export const configBaseUrl: String = process.env.NODE_ENV === 'development' ? 'http://127.0.0.1:8880' // 开发环境 : 'http://x.x.x.x:8880' // 生产环境 ;