如果你对这个库感兴趣,欢送Star
或提请Issue
,也能够成为这个库的贡献者。(如果有人能帮我翻译直达英文档或写测试用例,我将感激不尽)
请设想上面两个场景
1
有时候,在同一个页面上,存在多个局部,如下图所示。
而在这各个局部中又存在一些反复的数据,例如绿色局部,他们实际上对应的申请的是后端同一个内容。
这个时候,如果咱们采取的是对模块的每个组件块都发动一次申请,很显著,这三个能够共享返回值的申请反复了。
对于这三个反复的申请,是否有方法只发动一次申请,而后三个申请共享同一个返回值呢?
2
假如有一个组件提供部分刷新或者加载的性能。
有时候用户点击刷新的时候,因为手抖或者其它未知的起因,总之就是点了不止一下,可能点了好几下,导致间接发送了好几次申请。
对于这好几次申请,是否可能进行整合,只发送了一次申请呢?
once-init
你当然能够本人设计一个简单的逻辑,封装一个绝对平安的组件。又或者,你能够试试 once-init
?
github npm
Promise Function Init Once, Use Everywhere.
只会被初始化一次的 Promise
函数。
第一次调用对象的时候会执行
Promise
函数初始化,反复调用,初始化将不会再次执行。同一个
Promise
不会在同一时间内被执行两次。压缩后大小
承诺
OnceInit
封装的Promise Function
,永远不会在同一时间被执行两次。- 如果上一个
Promise Function
没有执行实现就调用了下一个Promise Function
,那么下一个Promise Function
将共享上一个Promise Function
的Promise
。
示例
假如存在一个 axios
Promise
申请,返回值类型为 number
,值为 777
。
const requestNumber = async () => { const res: AxiosResponse<number> = await axiosInstance.get("/api/number"); return res.data;};
你能够应用 oi
来封装这个 Promise
函数
const oiInstance = oi(requestNumber);
当初,你能够在任何中央调用这个实例。
init
假如有两个办法 functionA
和 functionA
,都须要发送这个申请。
async function functionA() { ... const res = await oiInstance.init(); ...}async function functionB() { ... const res = await oiInstance.init(); ...}
而你须要在某个文件中,须要同时应用这两个办法。
async function functionC() { await functionA(); await functionB();}function functionD() { functionA(); functionB();}
对于 functionC
, 在第一次执行 init
之后,oiInstance
将会保留 Promise
的执行后果,尔后再执行 init
,将不会再收回 Promise
申请。
对于 functionD
, api
申请只会发送一次,functionA
和 functionB
中的 res
都将期待同一个申请的返回值,不会发送反复的申请。
target
target
能同步获取返回值。
function functionE() { ... const res = oiInstance.target; ...}
如果在获取 target
之前曾经实现初始化,target
的值为 Promise
的返回值,否则,target
的值为 undefined
。例如,
const res = oiInstance.target; // undefined
await oiInstance.init();const res = oiInstance.target; // [Return Value] 777
请留神,尽管是同步获取,但 once-init
依然会认为你此时须要发出请求,因而调用 target
属性也会开始初始化。
在上面这个例子中,咱们假如 api
的申请时长是 10s
。在上面这个例子里,申请在第一行的时候就曾经收回。
const res = oiInstance.target; // undefined/** Promise has been executed. */setTimeout(async () => { const resAfter = oiInstance.target; // [Return Value] 777 const intAffter = await oiInstance.init(); // [Return Value] 777 , Promise will not be executed again. /** Since The Promise has been executed before, it will not be executed again. */}, 10001);
和同时先后同步执行两次 init
一样,如果在获取 init
之前拜访了 target
属性,而 拜访 target
导致的 Promise
申请没有完结的话,init
将间接期待上一个 Promise
完结并返回上一个 Promise
的返回值 。
上面这个例子将会帮忙你了解。
const res = oiInstance.target; // undefinedsetTimeout(async () => { const resAfter = oiInstance.target; // undefined const intAffter = await oiInstance.init(); // [Return Value] 777 /** Since The Promise has been executing it will not be executing again. */ /** After About 8000ms, The Value will be return by the first promise done */}, 2000);
这里的 init
将会期待上一个 Promise
函数执行的返回值,因为 init
是在 200ms
之后才执行的,所以它只须要再期待大概 800ms
就能取得这个返回值了。
defaultValue
应用 target
属性通常须要搭配默认值,而 oi
的第二个参数能够为你的 Promise
定义默认值。
const defaultValue = -1;const oiInstance = oi(requestNumber, defaultValue);const ans = oiInstance.target; // -1
refresh
你如果想要更新实例的值,则须要调用 refresh
。
假如第一次加载的值是 777
,而刷新之后的值是 888
。
const ans = await oiInstance.init(); // [Retrun Value] 777const ansAfterRefresh = await oiInstance.refresh(); // [Retrun Value] 888
刷新之后,调用 init
和 target
获取的值会变成新的值。
oiInstance.target; // undefinedawait oiInstance.init(); // [Promise Retrun Value] 777oiInstance.target; // 777await oiInstance.refresh(); // [Promise Retrun Value] 888/** Promise will not be exectued */oiInstance.target; // 888await oiInstance.init(); // 888
你能够间接应用 refresh
来执行初始化,在初始化上,它和 init
的成果统一。
oiInstance.target; // undefinedawait oiInstance.refresh(); // [Promise Retrun Value] 777oiInstance.target; // 777await oiInstance.refresh(); // [Promise Retrun Value] 888oiInstance.target; // 888
如果同步先后调用了两次 refresh
,两次 refresh
将期待同一个申请的返回值,不会发送反复的申请。
async function functionA() { console.log("A", await oiInstance.refresh());}async function functionB() { console.log("B", await oiInstance.refresh());}functionA(); // 'A', [Promise Retrun Value] 777functionB(); // 'B', [Promise Retrun Value] 777/** only one promise is executed *//** functionA and functionB share A same promise and promise return value */
咱们依然假如 api
申请的时长为 10s === 10000ms
。
oiInstance.refresh();setTimeout(async () => { await oiInstance.refresh();}, 2000);/** After 10000ms, two refresh will be exected at the same time */
如果异步先后调用了两次 refresh
,那么发送两次申请。
async function functionA() { console.log("A", await oiInstance.refresh());}async function functionB() { console.log("B", await oiInstance.refresh());}await functionA(); // 'A', [Promise Retrun Value] 777await functionB(); // 'B', [Promise Retrun Value] 888/** Two different promises were executed */
如果你感觉逻辑太过简单,那请至多要记住一点,OnceInit
封装的 Promise Function
,永远不会在同一时间被执行两次。
除此之外,once-init
还提供了其它的 api
,以满足更多的需要,但以上是它的次要性能。更多信息请查看 once-init 的 github 。
HELP
我还将把公布一个 Vue3-Composition Api
的版本。(预约中)
export abstract class RefOnceInit<T, G = T> extends OnceInit< Ref<T | undefined>, G> { loading = ref<boolean>(false); protected abstract factory(raw: G, observe: Ref<T | undefined>): void; constructor(defaultValue?: T) { const refed = ref<T>(); refed.value = defaultValue; super(refed); this.onLoading((event) => { this.loading.value = event; }); }}
这样 RefOnceInit
就是一个响应式的对象。对于 OnceInit
类请查看源码。
当申请实现的时候,就能引发页面 UI
的变动。