小程序生命周期里的异步执行问题

前言

这篇文章主要想把之前主导的一个技术项目中,关于处理小程序生命周期内异步问题提炼一下。主要的场景就是在用户扫码进入小程序时,首先触发小程序的 onLoad 方法,在 onLoad 内可能发起请求解析太阳码中的参数,得到的参数如果参与了 onShow 内部的逻辑。
但则要面临一个问题:onLoad 和 onShow 是同步执行的,但由于 onLoad 内部存在异步请求过程,导致 onShow 中的逻辑可能先执行,从而导致报错,业务流程中断。

onLoad:页面第一次加载时触发,从跳转页面返回时不能触发,可以传递参数
onShow:页面显示或从后台跳回小程序时显示此页面时触发,从跳转页面返回时触发,不能传递参数

问题示例

具体的过程如下:

import {formatSceneHelper} from '@/utils/helper/getSceneParams'

onLoad(params) {
  const {scene} = params
  // getSceneParams 为异步请求
  formatSceneHelper(async getSceneParams => {
     将出参赋值给全局变量。。。
  })
},
onShow() {
    读取全局变量。。。
}

由代码可见,onShow 内部的逻辑如果对 getSceneParams 返回的参数有强依赖的话,就会导致因为生命周期执行顺序的同步关系,而取不到数据;

解决方案

我们可以采取如下设计

const getSceneParams = () => {
  return new Promise((resolve) => {
    setTimeout(() => {
      console.log(3);
      resolve();
    }, 500);
  });
};
const formatSceneHelper = (productionFunction) => {
  let cb,
    promiseDone = false;
  productionFunction(getSceneParams).then(() => {
    promiseDone = true;
    console.log(4);
    if (cb) {
    // onLoad执行后调用onShow的逻辑
      console.log(5);
      cb();
    }
  });
  return (callback) => {
    console.log(2);
    cb = callback;
    // 利用闭包保存onLoad中的promiseDone
    if (promiseDone) {
    // 单独触发onShow时被调用
      console.log(7);
      cb();
    }
  };
};

const promiseDoneFun = formatSceneHelper(() => {
  console.log(1);
  return getSceneParams();
});
promiseDoneFun(() => console.log(6));
//1,2,3,4,5,6

上述代码中 cb() 即为 onShow 的业务逻辑封装的回调函数,
模拟页面初始化同步执行 onLoad 和 onShow 后,代码的打印顺序即为1-6;
之后单独触发 onShow 时,由于闭包的存在,变量 promiseDone 会被读取到,从而打印7

在页面中的调用

为确保参数正常拿到后再去参与业务逻辑,务必要在onLoad中生成闭包(this.promiseDoneFun),并将onShow内通过接口拿到的参数的逻辑作为回调函数传进去

onLoad(params) {
  const {scene} = params
  this.promiseDoneFun = formatSceneHelper(async getSceneParams => {
      ....
  })
}
onShow() {
  this.promiseDoneFun(()=>{
    。。。
  })
}

这样就解决了onLoad和onShow可能涉及到的异步问题

你可能感兴趣的:(前端,react.js)