避免复杂异步函数重复执行

354 阅读1分钟

在开发的过程中可能会遇到代码中包含复杂异步函数, 若返回结果相同或一定时间内返回结果相同. 可以使用如下写法来避免对于该复杂异步函数的重复执行.

// 重复执行复杂异步函数

const complexAsyncFn = () => new Promise((resolve) => {
  setTimeout(() => {
    const year = new Date().getFullYear();
    console.log(`complexAsyncFn: ${year}`)
    resolve(year);
  }, Math.round(Math.random() * 4096));
})



setTimeout(async() => {
  const year = await complexAsyncFn();
  console.log(`q1: ${year}`)
}, Math.round(Math.random() * 1024));

setTimeout(async() => {
  const year = await complexAsyncFn();
  console.log(`q2: ${year}`)
}, Math.round(Math.random() * 1024));

setTimeout(async() => {
  const year = await complexAsyncFn();
  console.log(`q3: ${year}`)
}, Math.round(Math.random() * 1024));

setTimeout(async() => {
  const year = await complexAsyncFn();
  console.log(`q4: ${year}`)
}, Math.round(Math.random() * 1024));

/*
=> complexAsyncFn: 2022
=> q3: 2022
=> complexAsyncFn: 2022
=> q1: 2022
=> complexAsyncFn: 2022
=> q2: 2022
=> complexAsyncFn: 2022
=> q4: 2022
*/

// complexAsyncFn 被执行了3次
// 避免重复执行复杂异步函数

const complexAsyncFn = () => new Promise((resolve) => {
  setTimeout(() => {
    const year = new Date().getFullYear();
    console.log(`complexAsyncFn: ${year}`)
    resolve(year);
  }, Math.round(Math.random() * 4096));
})

let answer = undefined;
const listeners = [];

const messenger = () => new Promise((resolve) => {
  if (answer !== undefined) { return resolve(answer); }

  listeners.push(resolve);
  
  if (listeners.length === 1) {
    complexAsyncFn().then((result) => {
      answer = result;
      listeners.forEach((listener) => listener(result));
      listeners.length = 0
    });
  }
});

setTimeout(async() => {
  const year = await messenger();
  console.log(`q1: ${year}`, new Date().getTime())
}, Math.round(Math.random() * 1024));

setTimeout(async() => {
  const year = await messenger();
  console.log(`q2: ${year}`, new Date().getTime())
}, Math.round(Math.random() * 1024));

setTimeout(async() => {
  const year = await messenger();
  console.log(`q3: ${year}`, new Date().getTime())
}, Math.round(Math.random() * 1024));

setTimeout(async() => {
  const year = await messenger();
  console.log(`q4: ${year}`, new Date().getTime())
}, Math.round(Math.random() * 1024 + 4096));

/*
=> complexAsyncFn: 2022
=> q1: 2022 1658819426219
=> q2: 2022 1658819426219
=> q3: 2022 1658819426219
=> q4: 2022 1658819427634
*/

// complexAsyncFn 被执行了1次, q1, q2, q3 同时获得了结果, q4 直接获得了结果