共计 4673 个字符,预计需要花费 12 分钟才能阅读完成。
如果你对这个库感兴趣,欢送
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; // undefined
setTimeout(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] 777
const ansAfterRefresh = await oiInstance.refresh(); // [Retrun Value] 888
刷新之后,调用 init
和 target
获取的值会变成新的值。
oiInstance.target; // undefined
await oiInstance.init(); // [Promise Retrun Value] 777
oiInstance.target; // 777
await oiInstance.refresh(); // [Promise Retrun Value] 888
/** Promise will not be exectued */
oiInstance.target; // 888
await oiInstance.init(); // 888
你能够间接应用 refresh
来执行初始化,在初始化上,它和 init
的成果统一。
oiInstance.target; // undefined
await oiInstance.refresh(); // [Promise Retrun Value] 777
oiInstance.target; // 777
await oiInstance.refresh(); // [Promise Retrun Value] 888
oiInstance.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] 777
functionB(); // '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] 777
await 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
的变动。