• 请不要在回答技术问题时复制粘贴 AI 生成的内容
firhome
V2EX  ›  程序员

wx 小程序的全局异步数据你们是如何加载管理的?

  •  3
     
  •   firhome · Jan 15, 2021 · 5523 views
    This topic created in 2125 days ago, the information mentioned may be changed or developed.
    向各位开发过小程序的大佬们请教个问题。

    我有一个小程序,需要初始化一些远程数据 放全局 ( 小程序的各个页面可能都会使用到 )

    所以在 app onLaunch 的时候去请求~ 但是小程序页面并不会等 这个异步请求结束后再加载。所以会导致页面报错。

    那么官方给的解决方案是 app 里写 callback 。 我有很多页面都会用到这部分数据 可又不可能 每个页面去写 callback 。



    我自己想了两个解决方案。

    1. 小程序 onLaunch 的时候去本地存储找是否有这部分数据,如果有 不请求(直接使用,页面不会报错),如果没有那请求之后 再重新调用 pages 的 onload 加载一次(类似网页刷新) 页面。

    2.做一个空白( loading )页面当首页,等数据都加载好了 再跳 其它页面。

    想问问大家是怎么解决呢?
    35 replies  •  2021-01-30 14:59:09 +08:00
    undertonememorie
    undertonememorie
    Jan 15, 2021
    1
    在代码不做大改动情况下推荐第二种
    linkopeneyes
    linkopeneyes
    Jan 15, 2021
    2
    如果没有那请求之后 再重新调用 pages 的 onload 加载一次(类似网页刷新) 页面。
    为什么不直接调用那个请求?
    firhome
    firhome
    OP
    Jan 15, 2021
    3
    @sjhhjx0122 我描述错误,没加载的话 是要再请求一下接口 然后再重新 onload
    MIUIOS
    MIUIOS
    Jan 15, 2021
    4
    onLaunch 不建议做网络请求
    firhome
    firhome
    OP
    Jan 15, 2021
    5
    @totoro52 为什么呢,那这种该写到哪里呢
    hereIsChen
    hereIsChen
    Jan 15, 2021
    6
    我们用的第二种方法,给了个加载页
    hereIsChen
    hereIsChen
    Jan 15, 2021
    7
    类似 app 的启动页面
    hiro0729
    hiro0729
    Jan 15, 2021
    8
    写个通用的方法,里面先判断是否 globalData 里有没有数据,有直接 resolve,没有异步取得后 resolve,各个页面的 onShow:async ()=>{}或 onLoad:async ()=>{}里,都先 await 调用一下这个方法
    varzy
    varzy
    Jan 15, 2021
    9
    我使用的方法类似于 8 楼,只不过是用了回调的语法。简单给个 demo 吧,写得不好勿喷。

    <script async src="//jsfiddle.net/varzy/nk2071se/1/embed/js/"></script>
    sujin190
    sujin190
    Jan 15, 2021
    10
    或者在全局重新定义一下 Page,这样就是可以直接替换掉每个页面的 onLoad 方法,加入等待 onLaunch 加载完的流程就好了
    varzy
    varzy
    Jan 15, 2021
    11
    @varzy #9 不知道怎么插入 jsfiddle 的预览。。。放个链接吧: https://jsfiddle.net/varzy/nk2071se/1/
    linkopeneyes
    linkopeneyes
    Jan 15, 2021
    12
    @firhome 那就最简单方式,封装一下请求,在发送请求之前判断一下 globalData 里有没有数据,没有数据就先发全局数据的那个请求,拿到数据在请求当前请求
    firhome
    firhome
    OP
    Jan 15, 2021
    13
    @sujin190 我正在尝试这个方法,但发现 onLoad 会不停的重新加载,有 demo 可以学习下吗?
    tjxone
    tjxone
    Jan 15, 2021
    14
    将获取去全局数据的方法挂载再 app.js 上,该方法用 promise 封装好,作好缓存判断
    后面每个页面的请求都先调用这个方法再请求各自页面的数据就可以了

    app.js
    getGlobalData(){return new Promise((resolve,reject)=>{ 先判断有无全局数据,无就请求数据再 resolve })}

    其他各个页面
    getApp().getGlobalData.then(自己的业务)
    sam014
    sam014
    Jan 15, 2021
    15
    第二项感觉不错,顺便还能加个开屏广告,2333333333333

    小程序用的 taro+mobx,全局数据放 mobx + run 调用 ,感觉比原生语法方便多了
    MIUIOS
    MIUIOS
    Jan 15, 2021
    16
    @firhome 因为你在这里做网络请求,如果你从服务器拉取一些特定的全局属性,还没拉取完就加载下个方法了 因为它是异步的,如果下面的方法用到这些属性就炸了 ,如果你非要在这做请求,你的第二个方案是可以的
    tjxone
    tjxone
    Jan 15, 2021
    17
    @sam014 第二项的话,如果分享页面就无法跳过去了
    sam014
    sam014
    Jan 15, 2021
    18
    @tjxone 没有完美的方案,有舍有得,所以我选 taro+mobx
    cczeng
    cczeng
    Jan 15, 2021
    19
    弱弱的问一下,发布订阅模式不适用吗
    phpcxy
    phpcxy
    Jan 15, 2021
    20
    第二个方案没考虑非首页进入的情况啊?
    preach
    preach
    Jan 15, 2021
    21
    zhyl
    zhyl
    Jan 15, 2021
    22
    第二种方案,然后在 app.onShow 中进行数据加载和页面跳转
    MENGKE
    MENGKE
    Jan 15, 2021
    23
    可以用 defineProperty 吧,或者 ES6 的 proxy ;
    https://blog.csdn.net/qq_17497931/article/details/108109947
    nekochyan
    nekochyan
    Jan 15, 2021
    24
    我们的解决方案 第一步就像你说的那样 onLaunch 的时候去本地存储找是否有这部分数据,如果有不请求,直接使用
    第二个是写一个通用的事件通知,没数据的话注册监听在 onLaunch 里面,然后数据返回的时候 trigger 一下事件所有监听的地方就刷新了
    nekochyan
    nekochyan
    Jan 15, 2021
    25
    就是楼上说的发布订阅模式
    lutian
    lutian
    Jan 15, 2021
    26
    aa
    GzhiYi
    GzhiYi
    Jan 15, 2021
    27
    响应式原理可解。
    懒得写的话用 omix 。
    https://github.com/Tencent/omi/tree/master/packages/omix
    miloooz
    miloooz
    Jan 15, 2021
    28
    我做了些封装
    1. app.ts 检查 token 是否存在,存在则直接请求 token,不存在则先请求 token,再请求全局公共数据(这里的判断是放在 store 里的)
    2. 封装 http 请求,没有 token 则拦截所有的请求,先把 token 请求到再把拦截的请求全部放行(这里的判断是放在 http 的封装里的)

    有一种情况就是,页面内的请求依赖全局的内容时,这里涉及到顺序。页面我用了 computed 插件,watch 监听 store 里被依赖的数据。如果被依赖的数据为空,则不执行,等到 app.ts 里请求到了全局公共数据,触发 wetch,再请求。
    SakuraKuma
    SakuraKuma
    Jan 15, 2021
    29
    patch 一下 Page, hook 一下 onload 加绑个事件, app 获取完数据 trigger/emit.
    miloooz
    miloooz
    Jan 15, 2021
    30
    全局的 store 和 computed 插件 这个官方的扩展里都有,引到项目里用就可以了
    https://developers.weixin.qq.com/miniprogram/dev/extended/utils/computed.html
    miloooz
    miloooz
    Jan 15, 2021
    31
    啊 上面的写错了
    1. app.ts 检查 token 是否存在,存在则直接请求全局公共数据,不存在则先请求 token,再请求全局公共数据(这里的判断是放在 store 里的)
    yehuzi
    yehuzi
    Jan 15, 2021
    32
    发布 /订阅模式应该可以解决楼主的问题吧: https://aotu.io/notes/2017/01/19/wxapp-event/
    looppppp
    looppppp
    Jan 15, 2021
    33
    接管 Page 全局方法,代理一下 onLoad 这些生命周期方法,然后就可以接入 redux 了,爽歪歪
    ersic
    ersic
    Jan 15, 2021 via Android
    34
    了解一下预加载跟周期性拉取得特性
    cxe2v
    cxe2v
    Jan 30, 2021
    35
    我写的方案是,第一次 lanuch 的时候获取全局数据,存到 app.js 的一个自定义的全局变量里,以后页面上要用自己去 app.globalData 里去拿,当然小程序是有一个加载界面的,在 lanuch 的时候一直处于加载动画上,所以用户体验稍微好一点
    About   ·   Help   ·   Advertise   ·   Blog   ·   API   ·   FAQ   ·   Privacy   ·   Solana   ·   926 Online   Highest 6679   ·     Select Language
    创意工作者们的社区
    World is powered by solitude
    VERSION: 3.9.8.5 · 117ms · UTC 21:19 · PVG 05:19 · LAX 13:19 · JFK 16:19
    ♥ Do have faith in what you're doing.