第二章:uniapp整合axios之真机测试两问题
上一章节,笔者编写了uniapp整合axios并实现前后端跨域请求的方案,完成了这些基本配置后,在浏览器端的测试基本是可以完成了,但是当笔者将程序运行到手机时,却出现了新的请求问题。
1、前置条件:配置环境
由于在真机测试的过程中,需要模仿服务端上云的模拟操作,因此笔者决定使用工具将本地服务映射到公网上。笔者使用的Coplar
内网穿透工具。
使用内网穿透工具,将本地服务映射到公网,这样手机端便可以通过公网访问本地服务:
将本地服务端地址:http://127.0.0.1:7777
映射到公网的域名地址:http://726d23e3.r2.cpolar.top
设置完内网映射后,配置前端的请求代理。
修改 manifest.json
中的代理地址
"h5": {
"devServer": {
"hot": true,
"port": 8080,
"disableHostCheck": true,
"proxy": {
"/api": {
"target": "http://726d23e3.r2.cpolar.top",
"changeOrigin": true,
"secure": false,
"pathRewrite": {
"^/api": ""
}
}
}
}
}
基本的模拟真实网络的环境已经搭建完成了,下面进行真机测试啦。
2、前置知识:条件编译
由于以下问题是通过 条件编译的判断来解决的,因此笔者先带大家熟悉一下条件编译的基本概念。
重点需要关注一下#ifdef
和endif
这两个关键词。
它的作用是:当标识符已经被定义过(一般是用#define命令定义),则对程序段1进行编译,否则编译程序段2。
先了解一下如何使用这两个关键词实现条件编译:
#ifdef 判断条件
程序段1
#else
程序段2
#endif
这就如何基本的if-else判断,只不过这层判断发生在编译阶段而非运行阶段。笔者相信读者还是很容易理解的。
3、所遇问题
问题一、真机测试网络请求失败问题
配置完成后,首先本地测试后台地址是否可以正常访问,当将app部署到手机上时,却出现无法访问网络的问题,且服务端也一直没有打印日志,为了进一步探究问题,于是在axios.js
文件内的响应拦截中添加结果打印。
// 响应拦截
service.interceptors.response.use(res => {
if (res.status == 200) {
// 请求成功后设置token
if (res.data.code == 100) {
}
return res.data;
} else {
console.log(res);
return Promise.reject(res.data.msg);
}
});
结果如下:
毫无疑问,请求并没有发送出去,仍然有跨域问题,那么如何解决呢,还记得笔者在manifest.json
文件中的代理配置吗?只配置H5,而非全部场景,那么在真机场景是如何配置代理请求呢?
let baseUrl = null
if (process.env.NODE_ENV === 'development') {
//开发环境
// #ifdef H5
// 如需跨域参照以下h5跨域配置
baseUrl = "/api"
// #endif
// #ifdef APP-PLUS ||MP
baseUrl = "http://726d23e3.r2.cpolar.top"
// #endif
} else {
baseUrl = ""
}
const service = axios.create({
baseURL: baseUrl,
timeout: 6000,
})
就这样便可以实现在真机环境的网络请求,第一个问题解决了,真机环境下网络请求通了。那么还有问题吗?是的笔者还遇到一个问题。
问题2、响应头中取空值令牌
服务端在返回请求时会在请求头中存入token
,并以"token"字符串为键值,然而在真机测试中,以"token"为键值,在请求头(header)中取出后端生成的令牌时,却出现空值。
1、第一步:复现取空值问题
service.interceptors.response.use(res => {
if (res.status == 200) {
// 请求成功后设置token
if (res.data.code == 100) {
console.log("=====response返回值=======");
console.log(res.header);
}
return res.data;
} else {
return Promise.reject(res.data.msg);
}
});
打印结果如下:
笔者惊讶的发现,为什么在真机测试阶段,header中的令牌键值由后端赋值的token
变成了Token
呢?
既然发现了问题,那么接下来便是解决它。
2、利用条件编译解决这个问题
根据上文大家知道在浏览器测试阶段,可以正常在响应头中取出token字符串的value值,而在真机测试阶段,则需要从响应头中取出Token字符串的value值,因此使用条件编译
实现在不同场景的不同操作。
// 二、响应头的二次处理做条件判断,解决不同token不同键值的问题
// 响应拦截
service.interceptors.response.use(res => {
if (res.status == 200) {
// 请求成功后设置token
if (res.data.code == 100) {
// #ifdef H5
uni.setStorageSync('token', res.header["token"]);
// #endif
// #ifdef APP-PLUS ||MP
uni.setStorageSync('token', res.header["Token"]);
// #endif
}
return res.data;
} else {
return Promise.reject(res.data.msg);
}
});
这样在本地调试阶段和真机测试阶段都可以取到响应头中请求令牌键值,至此uniapp整和axios在真机测试上的最后一个问题,算是完美解决了。
4、总结
以上是笔者开发一个简易app所遇到的问题,由于笔者非专业前端,如果表述或者概念不准确的地方,还请批评斧正呢,也希望文章能对大家有多帮助。