App启动流程

通常我们App在进入首页时,都需要做一些初始化工作,如申请权限,从服务器获取数据(user信息,App配置信息等),sdk初始化等。一般的App可能包含下面几个步骤:

  1. 用户协议和隐私政策(首次启动展示,需要用户同意才可进入app)
  2. 权限申请
  3. 用户登录状态判断
    3.1 未登录跳转登录页面
    3.2 已登录获取用户信息
  4. app基础配置信息获取(首页banner配置,部分活动配置等)
  5. 获取的完成后进入首页。

需求流程图

在这里插入图片描述

一种实现方式

针对上述需求,我们可以这样实现

<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)
		},
	}
}

上述实现方式可以满足需求,但是方法嵌套严重。
这样带来两个问题:

  1. 可读行差
  2. 可扩展性差

当启动流程有更改时,需要改动较多代码。
如在权限申请步骤后添加模拟器判断步骤,那么需要修改的方法有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

Logo

腾讯云面向开发者汇聚海量精品云计算使用和开发经验,营造开放的云计算技术生态圈。

更多推荐