uni-app async/await优化启动流程
uni-app async/await优化启动流程App启动流程需求流程图一种实现方式Async/Await改进方法弹框组件使用Promise方式异步请求Promise包装最终方案App启动流程通常我们App在进入首页时,都需要做一些初始化工作,如申请权限,从服务器获取数据(user信息,App配置信息等),sdk初始化等。一般的App可能包含下面几个步骤:用户协议和隐私政策(首次启动展示,需要用
uni-app async/await优化启动流程
App启动流程
通常我们App在进入首页时,都需要做一些初始化工作,如申请权限,从服务器获取数据(user信息,App配置信息等),sdk初始化等。一般的App可能包含下面几个步骤:
- 用户协议和隐私政策(首次启动展示,需要用户同意才可进入app)
- 权限申请
- 用户登录状态判断
3.1 未登录跳转登录页面
3.2 已登录获取用户信息 - app基础配置信息获取(首页banner配置,部分活动配置等)
- 获取的完成后进入首页。
需求流程图
一种实现方式
针对上述需求,我们可以这样实现
<template>
<view class="content">
<image class="logo" src="/static/logo.png"></image>
<view class="text-area">
<text class="title">text</text>
</view>
<protocolDialog ref="protocol_dialog" title="个人信息保护指引" protocolPath='/pages/pp/protocol'
policyPath='/pages/pp/policy' @protocol_confirm="protocol_confirm"></protocolDialog>
<permissionDialog ref="pd_dialog" @permissionDialogCancel="permissionDialogCancel"></permissionDialog>
</view>
</template>
export default {
onReady() {
const isAgreeProtocol = uni.getStorageSync("agree_protocol");
if (isAgreeProtocol) {
this.requestPermission();
} else {
this.$refs.protocol_dialog.open();
uni.setStorageSync("agree_protocol", true);
}
},
methods: {
//用户协议弹框用户选择同意
protocol_confirm(b) {
if (b) {
this.requestPermission();
}
},
//申请权限
requestPermission() {
const that = this;
permision.requestAndroidPermission("android.permission.CAMERA")
.then(res => {
if (res == -1) {
//被永久拒绝权限
this.$refs.pd_dialog.open();
} else {
const uid = uni.getStorageSync("uid");
const token = uni.getStorageSync("token");
if (!uid || !token) {
uni.redirectTo({
url: './login'
})
return;
} else {
that.getUser();
}
}
}).catch(err => {
})
},
//权限弹框选择取消
permissionDialogCancel(b) {
const uid = uni.getStorageSync("uid");
const token = uni.getStorageSync("token");
if (!uid || !token) {
uni.redirectTo({
url: './login'
})
return;
} else {
this.getUser();
}
},
//模拟用户登录
getUser(uid, token) {
setTimeout(() => {
const result = {
"uid": "123456",
"name": "张三"
}
uni.redirectTo({
url: './home'
})
}, 2000)
},
}
}
上述实现方式可以满足需求,但是方法嵌套严重。
这样带来两个问题:
- 可读行差
- 可扩展性差
当启动流程有更改时,需要改动较多代码。
如在权限申请步骤后添加模拟器判断步骤,那么需要修改的方法有permissionDialogCancel,requestPermission,以及新添加方法checkSimulator。
然后由于Android应用市场较多且规则不一,因而启动流程往往会有改动需求
比如“华为应用市场”要求,用户拒绝权限也必须能进入app体验相关内容
再比如“应用宝”要求,在用户同意隐私权限之后才可以进行网络请求,获取设备信息等操作
由于需求会有改动。这就要求我们的相关代码具有高扩展性。
Async/Await改进方法
使用Async/Await,可以将异步操作变成了同步的形式,逻辑更清晰。
针对上述代码,主要封两点优化
弹框组件使用Promise方式
之前使用了传统的prop,$emit方法,使得弹框的展示和确认逻辑分散了。使用Promise方法如下,
先看下最终的调用效果
this.$refs.protocol_dialog.openModal().then(res=>{}).catch(err=>{});
采用这样的方式,就可以使用async和await进行改进。
弹框具体实现逻辑如下:
<template name="reward-video-dialog">
<view @touchmove.stop.prevent="clear" v-show="isShow">
<view class="popup_mask" @touchmove.stop.prevent="clear"></view>
<view class="modal-content">
<view class='modal_title'>提示</view>
<view class='modal_textarea'>
为了给您提供更好的体验,请打开“手机拍照”权限,否则无法进入App哦!
</view>
<view class='buy_vip' @click='openPermission'>
打开权限
</view>
<view class='buy_count' @click='cancel'>
取消
</view>
</view>
</view>
</template>
<script>
import permision from "@/js_sdk/wa-permission/permission.js"
let permissions = []
export default {
data() {
return {
isShow: false
}
},
onShow() {
console.log("permissionDialog show");
},
methods: {
clear() {
return;
},
openPermission(){
permision.gotoAppPermissionSetting();
},
open(){
this.isShow = true;
},
openModal(){
this.isShow = true;
return new Promise((resolve,reject)=>{
uni.$on("permissionDialog" , function(res){
resolve(res);
})
uni.$on("permissionDialogError",function(){
reject();
})
})
},
cancel(){
this.$emit("permissionDialogCancel" , false);
uni.$emit("permissionDialog" , false);
this.isShow = false;
}
}
}
</script>
引用弹框的时候,既可以用传统的方式,也可以用Promise方式。
异步请求Promise包装
//模拟用户登录
getUser(uid , token){
return new Promise((resolve , reject)=>{
setTimeout(()=>{
const result = {
"uid":"123456",
"name":"张三"
}
resolve(result);
},2000)
})
},
这部分比较简单,就是Promise的基本用法。
最终方案
onReady() {
this.start();
},
methods: {
async start(){
//隐私权限
const isAgreeProtocol = uni.getStorageSync("agree_protocol");
if(!isAgreeProtocol){
await this.$refs.protocol_dialog.openModal();
uni.setStorageSync("agree_protocol" , true);
}
//权限申请
// const hasPermission = permision.judgeIosPermission("location");
// console.log(hasPermission);
const requestResult = await permision.requestAndroidPermission("android.permission.CAMERA");
console.log("requestResult = " +requestResult);
if(requestResult == -1){
const hasPermission = await this.$refs.pd_dialog.openModal();
}
//获取用户信息
const uid = uni.getStorageSync("uid");
const token = uni.getStorageSync("token");
if(!uid || !token){
uni.redirectTo({
url:'./login'
})
return;
}
await Promise.all([this.getUser(uid , token) , this.getOtherRequest()]);
uni.redirectTo({
url:'./home'
})
},
//模拟用户登录
getUser(uid , token){
return new Promise((resolve , reject)=>{
setTimeout(()=>{
const result = {
"uid":"123456",
"name":"张三"
}
resolve(result);
},2000)
})
},
//模拟网络请求
getOtherRequest(){
return new Promise((resolve , reject)=>{
setTimeout(()=>{
resolve(1);
},2000)
})
}
使用async/await后,不在有方法的嵌套,看起来就是同步的代码,可读性强。同时,若流程有修改,如之前的添加模拟器检测步骤,那么这次只需要添加模拟器方法,然后在start()方法相应位置添加即可。
//检测模拟器
checkSimulator(){
return new Promise((resolve , reject)=>{
setTimeout(()=>{
resolve(true);
},2000)
})
}
//start方法添加模拟器判断
const isSimulator = await this.checkSimulator();
if(isSimulator){
uni.showToast({
title:'禁止使用模拟器'
}
)
return;
}
//获取用户信息
const uid = uni.getStorageSync("uid");
const token = uni.getStorageSync("token");
if(!uid || !token){
uni.redirectTo({
url:'./login'
})
return;
}
有不好或者不对的地方欢迎指正
源码地址:https://gitee.com/BIN_CUH/uni-start-opt
更多推荐
所有评论(0)