小程序如何优先获取配置再调用别的接口?

cute_girl
  • 1.5k

具体就是在正常调用接口前,先调用一个获取全局配置的接口,然后再开始其他接口的调用。
我的想法是onLaunch里面调用,但是这样不能保证返回结果前其他接口不被调用,毕竟是异步的嘛,请问各位有什么好办法吗

回复
阅读 2.1k
5 个回答
✓ 已被采纳
let promise = null

function init() {
  if (promise) return promise

  promise = new Promise(resolve => {
    setTimeout(() => {
      console.log('初始化完成')
      resolve()
    }, 1000)
  })
}

function fn() {
  init().then(() => {
    console.log('已经初始化完成,继续执行fn')
  })
}

init()
fn()

setTimeout(() => {
  fn()
}, 2000)

setTimeout(() => {
  fn()
}, 3000)

增加个全局标志位,你记到 globalData 也好,直接挂载到 wx 上也行。

然后其他接口发起前先等待这个标志位变成 true,但因为 JS 本身没提供非阻塞式的异步锁,所以我们要利用 setTimeout 实现一个“伪”异步等待,大概这样:

function waitForFlag() {
  return new Promise((resolve) => {
    let fn = () => {
      if (wx['__FLAG']) {
        clearTimeout(timer);
        return resolve();
      }

      timer = setTimeout(fn, 100); // 可以自己控制等待间隔
    }
    let timer = setTimeout(fn, 0);
  });
}

waitForFlag().then(() => {
    wx.request();
});

// 什么时候控制 wx['__FLAG'] 变为 true 看你自己
// 甚至你还可以增加一个 timeout 参数,一定时间后直接 reject 掉那个异步等待

不要在任何生命周期调,而是封装你的请求方法,惰性前置请求,例如你进入小程序发起了一个首页接口,你这个请求封装就可以判断了,是否已经请求全局接口,否就请求先,是就正常请求

有一种设计模式叫做“回调-订阅”,很多人对它的第一印象是用来通信,其实如果加一个事件缓存,这个模式就可以用来管理相互依赖的异步操作
假如获取配置的接口是 getConfig(callback),某异步接口someApi 依赖 getConfig 的结果,那么使用 @君迹我心 开发的 event-watcher库的方法(因为这个库有缓存功能),就可以这样写:

import { emit, one } from 'path to event watcher file';

const CONFIG_READY = 'CONFIG_READY';

getConfig(res => {
    emit(CONFIG_READY, res, true);
    // 这里第三个参数置为 true,之前或之后的所有订阅都能收到此事件
});

one(CONFIG_READY, res => someApi(res), true);

事件缓存貌似是一个新的概念,可以用来应付 emitone 早的情形。

const loadConfig = (() => {
    let config;

    async function fetchConfig() {
        console.log("如果在一次获取未结束时多次 loadConfig,这个函数就可能调用多次");

        return new Promise(resolve => {
            setTimeout(
                () => resolve({
                    name: "config",
                    version: "1.0.1"
                }),
                1000);
        });
    }

    return async () => config ??= await fetchConfig();
})();


async function fetch1() {
    const config = await loadConfig();
    console.log("fetch1", config);
}

async function fetch2() {
    const config = await loadConfig();
    console.log("fetch2", config);
}

async function fetch3() {
    await new Promise(resolve => {
        setTimeout(resolve, 1500);
    });
    const config = await loadConfig();
    console.log("fetch3", config);
}

fetch1();
fetch2();
fetch3();
宣传栏