在微信小程序开发中APP.vue中的onlanch与首页index.vue中的onload的异步问题,在同时触发的情况下,如何保证先全部执行完onlanch中的代码,拿到返回值之后再去执行onload中的代码
比如:我想要在应用启动的时候去拿到openid或者是用户信息token...,在没有返回需要的数据之前,小程序却去执行首页index.vue中的onload,从而导致后续的代码没有openid的支持,没有openid导致token也拿不到,没有token就请求不到任何数据,从而导致用户一打开页面啥都看不到
写个deom
App.vue程序启动,用计时器进行异步
export default {
onLaunch: function() {
console.log('项目启动了')
setTimeout(()=>{
console.log('加载1')
setTimeout(()=>{
console.log('加载2')
setTimeout(()=>{
console.log('加载3')
},1000)
},1000)
},1000)
}
};
在首页index.vue onload中
onLoad() {
console.log('页面加载..')
setTimeout(()=>{
console.log('页面1')
setTimeout(()=>{
console.log('页面2')
setTimeout(()=>{
console.log('页面3')
},1000)
},1000)
},1000)
}
程序执行打印结果
执行顺序
onlanch同步=>onload同步=>onload异步=>onlanch异步
解决1
定时器延迟onload中的代码,但是在真实开发中这是不现实的,因为当用户网速不好的情况下,请求onlanch中的代码超过定时器的时间范围,就会执行onload里面的代码,所以还是一片空白,那用户网速好的时候,也不会过快的加载出来,而是等定时器运行完才会进行加载,这种有规定时间的解决办法算不上真正解决办法
解决2
ES6中提供了一个promise方案是一个不错的解决方法
promise是什么?
1、主要用于异步计算
2、可以将异步操作队列化,按照期望的顺序执行,返回符合预期的结果
3、可以在对象之间传递和操作promise,帮助我们处理队列
基本用法:
<script>
function runAsync() {
console.log('准备洗澡')
return new Promise(function (resolve, reject) {
//做一些异步操作
setTimeout(function () {
console.log("洗澡完成");
resolve("干干净净");
}, 2000);
});
}
// 如何用?
runAsync()
.then((res) => {
console.log(res);
})
</script>
把你原来写在APP.vue中的onlanch的代码拿出来,重新写一个方法
function login(){
return new Promise((resolve, reject)=>{
console.log('项目启动了')
setTimeout(()=>{
console.log('加载1')
setTimeout(()=>{
console.log('加载2')
setTimeout(()=>{
console.log('加载3')
//全部加载成功,在去加载onload
resolve()
},1000)
},1000)
},1000)
})
}
//暴露
export default login
在首页onload中
//导入
import login from '@/utils/token.js'
login().then(res=>{
console.log('页面加载..')
setTimeout(()=>{
console.log('页面1')
setTimeout(()=>{
console.log('页面2')
setTimeout(()=>{
console.log('页面3')
},1000)
},1000)
},1000)
})
执行过程
解决3
使用侦听器监听onlanch里的代码是否全部执行完毕
watch:{
//监听onlanch中的vuex中bol的数据改变执行
"$store.state.bol"(){
//一旦onlanch加载完毕,修改vuex数据,就执行以下代码
console.log('页面加载..')
setTimeout(()=>{
console.log('页面1')
setTimeout(()=>{
console.log('页面2')
setTimeout(()=>{
console.log('页面3')
},1000)
},1000)
},1000)
}
},
vuex代码
import Vue from 'vue'
import Vuex from 'vuex'
Vue.use(Vuex)
const store=new Vuex.Store({
state:{
//数据
bol:false
},
//方法
mutations:{
change(state,val){
state.bol=val
}
}
})
export default store
onlanch中代码
setTimeout(()=>{
console.log('加载3')
//修改vuex数据
store.commit('change',true)
},1000)
执行结果和以上情况一样,都可以解决
解决4
使用路由插件 uni-simple-router 可以拦截页面进入之前 并强化了onlaunch异步的问题,这也是目前最好的解决办法