前言

好久没写博客了,由于公司业务需要,最近接触uiapp比较多,一直想着输出一些相关的文章。正好最近时间富余,有机会来一波输出了。

问题描述

在使用 uni-app 开发项目时,会遇到需要在 onLaunch 中请求接口返回结果,并且此结果在项目各个页面的 onLoad 中都有可能使用到的需求,比如微信小程序在 onLaunch 中进行登录后取得 openid 并获得 token,项目各页面需要带上该 token 请求其他接口。

问题原因

在onLaunch 中的请求是异步的,也就是说在执行 onLaunch 后页面 onLoad 就开始执行了,而不会等待 onLaunch 异步返回数据后再执行,这就导致了页面无法拿到 onLaunch 中异步获取的数据。

解决问题

知道问题原因之后,解决起来就容易了。作为资深白嫖党,先是搜索了相关资料,发现了下面的解决方案。

解决方案一

既然在onLaunch中请求是异步的原因导致这个问题,那改成同步的不就行了,这里利用Promise来解决这个问题。步骤如下。

步骤一

在 main.js 中增加如下代码:

Vue.prototype.$onLaunched = new Promise(resolve => {
Vue.prototype.$isResolve = resolve
})

步骤二

在 App.vue 的 onLaunch 中增加代码 this.$isResolve(),具体如下:

onLaunch () {
uni.login({
provider: 'weixin',
success: loginRes => {
login({ // 该接口为我们自己写的获取 openid/token 的接口,请替换成自己的
code: loginRes.code
}).then(res => {
try {
console.info(res.data.token)
uni.setStorageSync('token', res.data.token)
this.$isResolve()
} catch (e) {
console.error(e)
}
})
}
})
}

步骤三

在页面 onLoad 中增加代码 await this.$onLaunched,具体如下:

async onLoad(option) {
await this.$onLaunched let token = ''
try {
token = uni.getStorageSync('token')
} catch(e) {
console.error(e)
} // 下面就可以使用 token 调用其他相关接口
}

有了这个解决方案,我就开始在实际项目中是用来了。但随着项目的复杂度增加,发现这个方案使用起来有一些弊端。每个页面都需要在 onLoad 中增加代码代码也太烦人了。

有没有更优雅的方案呢?继续查找资料,有个解决方案是定制一个页面钩子,然后注册全局的异步任务,定义钩子的触发条件,满足条件时即可自动执行页面里相关的钩子。相关方案见参考资料2。

但这个方案我也不太满意,仍然需要在页面添加一些函数去响应请求。后面突然想到,可以监听路由变动,在路由跳转之前完成请求。

解决方案二(推荐)

正好项目中用到了uni-simple-router插件,提供了全局前置守卫事件beforeEach,其本质是代理了所有的生命周期,让生命周期更加可控,这样就可以很好的解决我们面临的问题了。步骤如下:

步骤一

在 route.js 增加如下代码:

// 登录(可放在公共函数里面)
const login = () => {
return new Promise(function(resolve, reject) {
uni.login({
provider: 'weixin',
success: loginRes => {
login({ // 该接口为我们自己写的获取 openid/token 的接口,请替换成自己的
code: loginRes.code
}).then(res => {
resolve(res);
}, err => {
reject(err);
})
},
fail: err => {
reject(err);
}
});
});
} // 获取token(可放在公共函数里面)
const getToken = () => {
let token = ''
try {
token = uni.getStorageSync('token')
} catch(e) {
console.error(e)
}
return token;
} // 是否登录
let hasLogin = false;
router.beforeEach(async (to, from, next) => {
// 首次进来,没有登录并且token不存在先请求数据
if(!hasLogin&&!getToken()){
const res = await login();
try {
console.info(res.data.token)
uni.setStorageSync('token', res.data.token)
hasLogin = true
} catch (e) {
console.error(e)
}
}
next()
})

步骤二

在页面 onLoad 中直接就可以获取 token 并使用,具体如下:

onLoad(option) {
let token = ''
try {
token = uni.getStorageSync('token')
} catch(e) {
console.error(e)
} // 下面就可以使用 token 调用其他相关接口
}

这个解决方案就灵活很多,只需要在 route.js 中写入代码,其他任意地方都可以调用。不用担心新增页面忘记相关方法的引入,更加灵活自由。

由于这个解决方案基于uni-simple-router插件,在使用前需要引入这个插件。如果不想引入插件,可以自行实现代码生命周期功能。

PS:大家有更好的解决方案,欢迎在评论区交流。

参考资料

  1. uni-app 中利用 Promise 实现 onLaunch 异步回调后执行 onLoad
  2. 小程序app.onLaunch与page.onLoad异步问题的最佳实践
  3. 代理生命周期 | uni-simple-router

uni-app 中实现 onLaunch 异步回调后执行 onLoad 最佳实践的更多相关文章

  1. uni app中使用自定义图标库

    项目中难免会用到自定义图标,那在uni app中应该怎么使用呢? 首先, 将图标目录放在static资源目录下: 在main.js中引入就可以全局使用了 import '@/static/icon-o ...

  2. 前端入门20-JavaScript进阶之异步回调的执行时机

    声明 本系列文章内容全部梳理自以下几个来源: <JavaScript权威指南> MDN web docs Github:smyhvae/web Github:goddyZhao/Trans ...

  3. Bug预防体系(上千bug分析后总结的最佳实践)

    Bug预防体系(上千bug分析后总结的最佳实践) 原创 2017-08-16俞美玲 光荣之路 吴老的<selenium webdriver 实战宝典>出版了!  web常见产品问题及预防 ...

  4. js中页面加载完成后执行的几种方法及执行顺序

    在js和jquery使用中,经常使用到页面加载完成后执行某一方法.通过整理,大概是五种方式(其中有的只是书写方式不一样). 1:使用jQuery的$(function){}; 2:使用jquery的$ ...

  5. iOS系统中导航栏的转场解决方案与最佳实践

    背景 目前,开源社区和业界内已经存在一些 iOS 导航栏转场的解决方案,但对于历史包袱沉重的美团 App 而言,这些解决方案并不完美.有的方案不能满足复杂的页面跳转场景,有的方案迁移成本较大,为此我们 ...

  6. uni app中关于图片的分包加载

    因为在项目中使用了大量的静态资源图片,使得主包体积过大, 而把这些图片全部放到服务器又有点麻烦,就想能不能把图片也分包,但是直接放在分包下的话导致图片资源找不到了, 在社区中看到大佬分享的十分有用,特 ...

  7. 在浏览器中输入 www.baidu.com 后执行的全部过程

    现在假设如果我们在客户端(客户端)浏览器中输入http://www.baidu.com,而baidu.com为要访问的服务器(服务器),下面详细分析客户端为了访问服务器而执行的一系列关于协议的操作: ...

  8. 在浏览器中输入www.baidu.com后执行的全过程

    链接 http 请求过程——当我们在浏览器输入 www.baidu.com,然后回车之后的详解. 1)域名解析(域名 www.baidu.com变为 ip 地址). 1.浏览器搜索自己的DNS缓存(维 ...

  9. 在浏览器中输入www.taobao.com后执行的全部过程

    >>>点击网址后,应用层的DNS协议会将网址解析为IP地址: DNS查找过程: 1.        浏览器会检查缓存中有没有这个域名对应的解析过的IP地址,如果缓存中有,这个解析过程 ...

随机推荐

  1. HTML5+CSS3兼容收藏夹

    CSS3选择器兼容IE6~8: Selectivizr 使用方法: <!--[if (gte IE 6)&(lte IE 8)]> <script src="htt ...

  2. (SSM框架)实现小程序图片上传(配小程序源码)

    阅读本文约"2分钟" 又是一个开源小组件啦! 因为刚好做到这个小功能,所以就整理了一下,针对微信小程序的图片(文件)上传! 原业务是针对用户反馈的图片上传.(没错,本次还提供小程序 ...

  3. C++---继承和派生

    继承和派生 在C++中, 代码重用是通过继承机制来实现的 继承, 就是在一个已经存在的类的基础上, 再建议一个新类 从已经有的类派生出新的类, 派生类就继承了基类的特征, 包括成员和方法 继承可以完成 ...

  4. git设置本地与远程分支关联

    1.为了避免每次都进行验证,在git进行绑定ssh mkdir ~/.ssh ssh-keygen -t rsa -C "xxx@qq.com" 将生成的公钥粘贴到git中 2.本 ...

  5. 使用加强堆结构解决topK问题

    作者:Grey 原文地址: 使用加强堆结构解决topK问题 题目描述 LintCode 550 · Top K Frequent Words II 思路 由于要统计每个字符串的次数,以及字典序,所以, ...

  6. 洛谷 P1162 填涂颜色 DFS

    P1162 填涂颜色 https://www.luogu.com.cn/problem/P1162 qaq搜索好抽象啊,蒟蒻表示难以理解,搞半天才做出来一道题,很挫败www 思路 染色法.找墙壁外的连 ...

  7. 2021.12.08 P1848 [USACO12OPEN]Bookshelf G(线段树优化DP)

    2021.12.08 P1848 [USACO12OPEN]Bookshelf G(线段树优化DP) https://www.luogu.com.cn/problem/P1848 题意: 当农夫约翰闲 ...

  8. 2021.11.11 EXKMP

    2021.11.11 EXKMP https://www.luogu.com.cn/problem/P5410 下标以1开头: #include<cstdio> #include<i ...

  9. k8s入门之基础环境准备(一)

    一.在虚拟机中安装Ubuntu20.04.4系统 1.下载Ubuntu20.04.4服务器版本系统 下载链接地址如下: https://mirrors.tuna.tsinghua.edu.cn/ubu ...

  10. MySQL数据存储

    MySQL体系架构 客户端连接器 提供与MySQL服务器建立的支持.目前几乎支持所有主流的服务端编程技术,例如常见的 Java.C.Python..NET等,它们通过各自API技术与MySQL建立连接 ...