Skip to content
Xmo edited this page Oct 31, 2022 · 1 revision

refreshexceed会刷新init的缓存;

所有api都能接收参数,参数就是封装的源function的参数;

在下面的所有例子中:

我们假设 axios.get("xxx.com") 返回的值是一个递增的数字,即第 1 次请求,会返回1,第 2 次请求会返回2,第 n 次请求会返回n

我们假设 foo 的执行时间为 50ms;其它时间忽略不计;

OnceInit.init

最常用的api,无论你调用多少次,init都只会执行一次,并返回给你第一次执行(或缓存中)的结果。

async function foo() {
  const res = await axios.get("xxx.com");
  return res;
}

const oiFoo = oi(foo);

await oiFoo.init(); // 50秒后,返回 1
await oiFoo.init(); // 0秒后,返回 1
await oiFoo.init(); // 0秒后,返回 1

如果多个 init 同时执行(第二次调用的时候,第一次执行还没有完成),则第二次及之后的调用将会等待第一次执行的结果,然后返回第一次执行的结果;

setTimeout(oiFoo.init, 30); // 20秒后,执行完毕,返回 1
await oiFoo.init(); // 50秒后,执行完毕,返回 1

OnceInit.refresh

refresh 刷新 once-init 的缓存;如果你在第一次调用 init 之后,希望再执行一次 foo 更新后端数据,你可以执行 refresh

refresh 之后,再执行 oiFoo 将会返回刷新后的数据;

async function foo() {
  const res = await axios.get("xxx.com");
  return res;
}

const oiFoo = oi(foo);

await oiFoo.init(); // 50秒后,返回 1 (无缓存,所以执行)
await oiFoo.refresh(); // 50秒后,返回 2
// refresh 会刷新 init 的缓存
await oiFoo.init(); // 0秒后,返回 2 (已有缓存,所以不会执行)
await oiFoo.refresh(); // 50秒后,返回 3

如果refresh正在刷新,则在refresh结束前执行的init也会refresh结束结束后再返回值,而不会直接返回旧的缓存结果。

多个 refresh 如果在同一时间里同时调用,只会执行一次,并返回第一次执行的结果。【如果你希望同一时间里同时执行,会执行多次,请使用 exceed

setTimeout(oiFoo.refresh, 30); // 20秒后,执行完毕,返回 1
await oiFoo.refresh(); // 50秒后,执行完毕,返回 1

refreshinit 共享一个执行队列,这意味着如果 initrefresh 同时执行,也将只会执行一次并返回第一次执行的结果;

setTimeout(oiFoo.refresh, 30); // 20秒后,执行完毕,返回 1
await oiFoo.init(); // 50秒后,执行完毕,返回 1

OnceInit.get

getinit 的同步版本,相当于获取缓存;如果有缓存的值,那么 get 会返回缓存值;如果没有,则会返回 undefined

oiFoo.get(); // 返回 undefined (从未执行过,所以没有缓存)

await oiFoo.init(); // 50秒后,返回 1
oiFoo.get(); // 返回 1

OnceInit.execute

execute 会直接执行源函数,它既不会修改缓存,也不会插入执行队列。

await oiFoo.init(); // 50秒后,返回 1
await oiFoo.execute(); // 50秒后,返回 2
await oiFoo.init(); // 0秒后,返回 1 (缓存未更新)
await oiFoo.refresh(); // 50秒后,返回 3 (缓存更新,重新获取后端值,由于后端在上次execute请求中虽未更新缓存,但更新了后端,所以返回值为3)

OnceInit.wait

如果当前异步函数正在执行,wait会等待直到结束,如果异步函数没有执行,则立即返回。

wait 没有返回值;

await oiFoo.wait(); // 等待0秒

oiFoo.init();
oiFoo.get(); // 返回 undefined
await oiFoo.wait(); // 等待50秒
oiFoo.get(); // 返回 1

OnceInit.exceed

!!! 这是一个会造成理解困难的函数,请尽量不要和其它 api 混合使用

exceed 会强制执行函数,无论现在是否正在执行另一个相同的异步函数。

exceed 也会刷新缓存。

refreshinit 的执行受 exceed 影响,但 exceed 的执行不受 refreshinit 的影响;

await Promise.all([oiFoo.exceed(), oiFoo.exceed(), oiFoo.exceed()]); // 50秒后,返回 [1, 2, 3];

// exceed 会刷新缓存
await oiFoo.init(); // 0秒后,返回 3
await oiFoo.refresh(); // 50秒后,返回 4

如果 exceed 正在执行, refreshinit 将会返回 exceed 执行的结果;

注意(WARNING): 如果你不断地执行 exceed ,会导致执行队列不断地刷新,而同一时间执行的 refreshinit 将返回你执行 initrefresh 前最后一次执行exceed的结果。

不推荐你短时间多次调用 exceed ,它可能让你对返回结果造成困扰;大多数情况下,refreshexecute 会是更好的替代品。

请在理解下面这个例子的前提下在实际应用场景中应用 exceed

await Promise.all([oiFoo.refresh(), oiFoo.exceed()]); // 50秒后,返回 [1, 2];

await Promise.all([oiFoo.exceed(), oiFoo.refresh()]); // 50秒后,返回 [3, 3];

await Promise.all([oiFoo.exceed(), oiFoo.refresh(), oiFoo.init()]); // 50秒后,返回 [4, 4, 3];

await oiFoo.init(); // 0秒后,返回 4

await Promise.all([
  oiFoo.exceed(),
  oiFoo.refresh(),
  oiFoo.exceed(),
  oiFoo.refresh(),
  oiFoo.init(),
]); // 50秒后,返回 [5, 5, 6, 6, 4];

Clone this wiki locally