如果在你的uni-app项目里,出现以下情况:
1) 你希望用第1个uni.request请求返回的结果作为第2个uni.request请求的参数;
2)如果你发现Storage里存储的数据根本获取不到,或者即使获取到也是上一次没清空的历史数据,Storage传参失败;
3)你希望出现的代码执行顺序并没有按照你的预期顺序执行;
那么很显然,你需要让uni.request()异步请求变成同步请求,因为uni-app的官网没有提供同步请求方法uni.requestSync();
所以我们需要使用Promise去封装uni.request(),或者使用 async 和 await去封装uni.request(),这样
uni.request()就会按照同步的方式执行,就不会出现uni.request()中参数获得参数值早于其它的uni.request()请求返回的结果
接下来,我会分多个版本的小项目去录屏调式演示出现这种状况的原因:
温馨提示:每个演示项目里都会用的md5.js文件,我上传的md5.js文件下载地址如下:
链接:https://pan.baidu.com/s/1uANsO5zfh7Q4Lw0jvXPZgg
提取码:3wuo
本篇博文很长,请耐心阅读,即使uni-app的官网上也没有这么高质量的文章。
var md5 = require('./md5.js');
module.exports = {
sign : function(){
var greeting = "welcome to my world";
var greetingmd5 = md5.hex_md5(greeting)
uni.setStorageSync("greeting",greeting);
uni.setStorageSync("greetingmd5",greetingmd5);
console.log('sign-tool.js 开始打印输出以下内容:');
console.log("明文:"+greeting);
console.log("密文:"+greetingmd5);
console.log('sign-tool.js 结束打印输出');
}
}
整个v1版本的项目代码已全部贴完,我将录屏演示调试代码的执行流程,即使你知道代码会怎么运行,
再看看我发的小视频又不碍啥事,因为后面的几个项目范例的调试视频你是一定会看的。
范例1演示调试代码的视频如下:
链接:https://pan.baidu.com/s/1PoathVeL6yY8m2vZkn5IzQ
提取码:4azu
范例1调试工具的控制台会输出如下截图内容:
本范例流程执行正常 能按照我们预期的代码执行顺序运行。
范例2:
接下来演示的几个项目范例,我们都会用到PHP实现的Restful api 接口,用Redis作为数据存储服务器,
我将使用ThinkPHP 6.0.2这个最新版本框架来写后台数据接口。
在演示范例2之前,我们需要先把后台数据接口写好,接下来我们先来写PHP实现的后台代码吧。
phpStudy v8.1版 下载地址:https://www.xp.cn/download.html 安装到D:\phpstudy
Redis for Windows 64位版 下载地址:https://github.com/microsoftarchive/redis/releases/download/win-3.0.504/Redis-x64-3.0.504.msi
ThinkPHP6.0.2 下载地址:https://github.com/top-think/think/archive/v6.0.2.zip 解压到(WWW文件夹不包括v6.0.2文件夹) D:\phpstudy\WWW
composer下载地址:https://getcomposer.org/Composer-Setup.exe
安装composer.exe程序,一路Next就好,
当安装出现Choose the command-line PHP you want to use:请浏览选择php.exe文件的完整路径
D:\phpstudy\Extensions\php\php7.3.4nts\php.exe
接下来以更新安装的方式安装ThinkPHP项目需要的一切依赖文件
C:\Users\ZiGoo>D:
D:\>cd D:\phpstudy\WWW
D:\phpstudy\WWW>composer update topthink/framework
WWW\config\cache.php文件代码如下:
env('cache.driver', 'file'),
// 缓存连接方式配置
'stores' => [
'file' => [
// 驱动方式
'type' => 'File',
// 缓存保存目录
'path' => '',
// 缓存前缀
'prefix' => '',
// 缓存有效期 0表示永久缓存
'expire' => 0,
// 缓存标签前缀
'tag_prefix' => 'tag:',
// 序列化机制 例如 ['serialize', 'unserialize']
'serialize' => [],
],
// redis缓存
'redis' => [
// 驱动方式
'type' => 'redis',
// 服务器地址
'host' => '127.0.0.1',
// 缓存前缀
'prefix' => '',
// 缓存有效期 0表示永久缓存
'expire' => 0,
// 序列化机制 例如 ['serialize', 'unserialize']
'serialize' => [],
],
// 更多的缓存连接
],
];
WWW\route\app.php文件代码如下:
// +----------------------------------------------------------------------
use think\facade\Route;
// GET 'http://2977a2v278.zicp.vip/public/index.php/zigoo.token.generate'
Route::get('zigoo.token.generate','Token/generateToken');
// GET http://2977a2v278.zicp.vip/public/index.php/zigoo.tutorial.sign.call
Route::get('zigoo.tutorial.sign.call','Tutorial/callSign');
WWW\app\controller\Token.php文件代码如下:
$session_create_id,
'time' => $time
);
Cache::store('redis')->set($token['token'],$token['time'],3600);
exit(json_encode(['status' => 'ok','data' => $token]));
}
}
WWW\app\controller\Tutorial.php文件代码如下:
request->param('version');
Cache::store('redis')->incr('counter'); //记录接口被访问的次数
checkSign();//如果用户想获得本接口返回的数据,必须通过签名验证
return json_encode(['status' => 'ok', 'data' => '你访问的是被签名保护的Restful api 接口','version' => $version]);
}
}
WWW\app\common.php文件代码如下:
PHP后台代码已全部贴完。
uni-app项目结构截图如下:
var md5 = require('./md5.js');
module.exports = {
sign : function(apiServer,params = {}){
uni.request({
url: apiServer+'zigoo.token.generate',
method: 'GET',
success: res => {
console.log(res);
if(res.data.status != 'ok'){return ;}
var data = res.data.data;
console.log('明文:token'+data.token +' time:' + data.time);
var datamd5 = md5.hex_md5(data.token + data.time) + '-' + data.token;
console.log('密文:'+ datamd5);
// 记录在本地
uni.setStorageSync("token",datamd5);
uni.setStorageSync("time",data.time);
},
fail:function(e){
console.log(JSON.stringify(e));
}
});
}
}
import Vue from 'vue'
import App from './App'
Vue.config.productionTip = false
Vue.prototype.apiServer = 'http://2977a2v278.zicp.vip/public/index.php/';
App.mpType = 'app'
const app = new Vue({
...App
})
app.$mount()
范例2演示调试代码的视频如下:
链接:https://pan.baidu.com/s/1e-GK0lYFDkE1drp89LNQ1w
提取码:d9sh
多个异步请求uni.request()函数,全部异步的请求函数,每个请求输入参数的初始化都赋值完毕后,
才执行第1个异步请求,这样代码的执行逻辑就不对啦,我们需要的是第1个异步请求返回值作为第2
个异步请求的输入参数,因为异步请求输入参数获得参数值的执行时间早于所有异步请求GET和POST请求发出。
所以Storage传参就自然失败啦,这是个典型的错误范例,在范例3中我将封装异步请求按照同步的方式执行来更正这个错误的范例。
var md5 = require('./md5.js');
module.exports = {
// 注意async 和 await 的修饰写法,意思是让异步请求uni.request()封装到同步函数sign里执行
async sign(apiServer,params = {}){
// GET请求返回数据:{"data":{"status":"ok","data":{"token":"5qraetfdq8kqi339u4m2if6k0e","time":1589808256}}
var [e,res] = await uni.request({
url: apiServer+'zigoo.token.generate',
method: 'GET'
});
console.log(res);
if(res.data.status != 'ok'){return ;}
var data = res.data.data;
console.log('明文:token'+data.token +' time:' + data.time);
var datamd5 = md5.hex_md5(data.token + data.time) + '-'+ data.token;
console.log('密文:'+ datamd5);
// 记录在本地
uni.setStorageSync("token", datamd5); // 1f3907e22469764866dce02aba5e26a2-5qraetfdq8kqi339u4m2if6k0e
uni.setStorageSync("time", data.time); // 1589808256
/*uni.setStorage({
key: 'token',
data: datamd5,
success: function () {
console.log('success1');
}
});
uni.setStorage({
key: 'time',
data: data.time,
success: function () {
console.log('success2');
}
});*/
return;
}
}
import Vue from 'vue'
import App from './App'
Vue.config.productionTip = false
Vue.prototype.apiServer = 'http://2977a2v278.zicp.vip/public/index.php/';
App.mpType = 'app'
const app = new Vue({
...App
})
app.$mount()
链接:https://pan.baidu.com/s/1FThCIzp6J4j_wX9aP-MFOw
提取码:p8mq
从调试代码的视频中,我们很直观看到代码能够按照我们期望的自然顺序来执行代码啦,结论:范例3代码正确。
接下来在范例4中我将使用Promise来替代async和await来实现范例3同样的同步执行效果。
var md5 = require('./md5.js');
module.exports = {
sign(apiServer, params = {}) {
//注意 Promise取代 async 和 await的写法,同步函数sign把异步请求uni.request封装成同步的方式执行
return new Promise((resolve, reject) => {
// GET请求返回数据:{"data":{"status":"ok","data":{"token":"5qraetfdq8kqi339u4m2if6k0e","time":1589808256}}
uni.request({
url: apiServer + 'zigoo.token.generate',
method: 'GET',
success: (res) => {
console.log(res);
if (res.data.status != 'ok') {
return;
}
var data = res.data.data;
console.log('加密之前:token' + data.token + ' time:' + data.time);
var datamd5 = md5.hex_md5(data.token + data.time) + '-'+ data.token;
console.log('加密输出结果:' + datamd5);
// 记录在本地
uni.setStorageSync("token", datamd5); // 1f3907e22469764866dce02aba5e26a2-5qraetfdq8kqi339u4m2if6k0e
uni.setStorageSync("time", data.time); // 1589808256
resolve(res);
},
fail: (err) => {
console.log('request fail', err)
reject(err)
}
})
})
}
}
import Vue from 'vue'
import App from './App'
Vue.config.productionTip = false
Vue.prototype.apiServer = 'http://2977a2v278.zicp.vip/public/index.php/';
App.mpType = 'app'
const app = new Vue({
...App
})
app.$mount()
链接:https://pan.baidu.com/s/1vLDbfB25At8oAWI_ujCl3w
提取码:t74g
从调试代码的视频中,我们很直观看到代码能够按照我们期望的自然顺序来执行代码啦,结论:范例4代码正确。