如果你对这个库感兴趣,欢迎Star或者提交Issue,你也可以成为这个库的contributor。(如果有人能帮我翻译汉英文档或写测试用例,我将不胜感激)请想象以下两种场景1有时,在同一个页面上,有多个部分,如下图所示。而且每一部分都有一些重复的数据,比如绿色部分,其实对应的是后端请求的相同内容。这时候如果我们对模块的每个组件块都采用一个请求,很明显这三个可以共享返回值的请求是重复的。对于这三个重复的请求,有没有办法只发起一个请求,然后三个请求共享同一个返回值呢?2假设有一个组件提供局部刷新或加载功能。有时候用户点击刷新的时候,因为手抖或者其他不明原因,总之点击不止一次,可能是几次,导致直接发送了好几个请求。对于这几个请求,是否可以整合并只发送一个请求?Once-init当然可以自己设计一个复杂的逻辑来封装一个相对安全的组件。或者,您可以尝试一次初始化?githubnpmPromise函数初始化一次,随处使用。一个只会被初始化一次的Promise函数。Promise函数初始化会在对象第一次被调用时执行,重复调用则不会再次执行初始化。同一个Promise不能同时被fulfill两次。CompressedSizePromiseOnceInit封装的PromiseFunction永远不会同时执行两次。如果在前一个PromiseFunction完成之前调用下一个PromiseFunction,则下一个PromiseFunction将共享前一个PromiseFunction的Promise。该示例假设有一个axiosPromise请求,返回类型为数字,值为777。constrequestNumber=async()=>{constres:AxiosResponse=awaitaxiosInstance.get("/api/number");返回res.data;};可以用oi来封装这个Promise函数constoiInstance=oi(requestNumber);现在,您可以在任何地方调用此实例。init假设有两个方法functionA和functionA,都需要发送这个请求。异步函数functionA(){...constres=awaitoiInstance.init();...}asyncfunctionfunctionB(){...constres=awaitoiInstance.init();...}而你需要在一个文件中,这两种方法需要同时使用。异步函数functionC(){awaitfunctionA();等待functionB();}functionfunctionD(){functionA();functionB();}对于functionC,在init第一次执行后,oiInstance会保存Promise的执行结果,之后再执行init,不会再发起Promise请求。对于functionD,api请求只会发送一次,functionA和functionB中的res会等待同一个请求的返回值,不会重复发送请求。targettarget可以同步获取返回值。functionfunctionE(){...constres=oiInstance.target;...}如果在获取target之前已经完成初始化,则target的值为Promise的返回值,否则target的值为undefined。例如,constres=oiInstance.target;//undefinedawaitoiInstance.init();constres=oiInstance.target;//[ReturnValue]777请注意,虽然是同步获取的,once-init还是认为你需要一个请求,所以调用target属性也开始初始化。在下面的例子中,我们假设api的请求时长是10s。在下面的示例中,请求是在第一行发出的。constres=oiInstance.target;//undefined/**Promise已经执行。*/setTimeout(async()=>{constresAfter=oiInstance.target;//[返回值]777constintAffter=awaitoiInstance.init();//[返回值]777,Promise不会再次执行。/**由于之前已经执行过Promise,所以不会再执行。*/},10001);并且同时执行两次init同理,如果在获取到init之前访问了target属性,并且访问target导致的Promise请求还没有结束,init会直接等待上一个Promise结束,返回上一个的返回值承诺。下面的例子将帮助你理解。constres=oiInstance.target;//undefinedsetTimeout(async()=>{constresAfter=oiInstance.target;//undefinedconstintAffter=awaitoiInstance.init();//[返回值]777/**因为Promise一直在执行所以不会再次执行。*//**大约8000毫秒后,第一个完成的承诺将返回值*/},2000);这里init会等待最后一次Promise函数执行的返回值,由于init是在200ms后执行的,所以只需要等待800ms左右就可以拿到返回值。使用target属性的defaultValue通常需要匹配一个默认值,oi的第二个参数可以为你的Promise定义一个默认值。常量默认值=-1;constoiInstance=oi(requestNumber,defaultValue);constans=oiInstance.target;//-1refresh如果要更新实例的值,需要调用refresh。假设第一次加载的值为777,刷新后的值为888。constans=awaitoiInstance.init();//[返回值]777constansAfterRefresh=awaitoiInstance.refresh();//[RetrunValue]888刷新后调用init和target得到的值会成为新的值。oiInstance.target;//undefinedawaitoiInstance.init();//[Promise返回值]777oiInstance.target;//777awaitoiInstance.refresh();//[Promise返回值]888/**Promise不会被执行*/oiInstance.target;//888awaitoiInstance.init();//888可以直接使用refresh进行初始化。在初始化方面,它和init的作用是一样的。oiInstance.target;//undefinedawaitoiInstance.refresh();//[Promise返回值]777oiInstance.target;//777awaitoiInstance.refresh();//[承诺返回值]888oiInstance.target;刷新被调用了两次,两次刷新都会等待同一个请求的返回值,不会发送重复的请求。asyncfunctionfunctionA(){console.log("A",awaitoiInstance.refresh());}asyncfunctionfunctionB(){console.log("B",awaitoiInstance.refresh());}functionA();//'A',[Promise返回值]777functionB();//'B',[PromiseRetrunValue]777/**只执行了一个promise*//**functionA和functionB共享一个相同的promise和promise返回值*/我们仍然假设api请求的时长是10s===10000毫秒。oiInstance.refresh();setTimeout(async()=>{awaitoiInstance.refresh();},2000);/**10000ms后,会同时执行两次刷新*/如果异步调用两次刷新,则发送请求两次。asyncfunctionfunctionA(){console.log("A",awaitoiInstance.refresh());}asyncfunctionfunctionB(){console.log("B",awaitoiInstance.refresh());}awaitfunctionA();//'A',[Promise返回值]777awaitfunctionB();//'B',[PromiseRetrunValue]888/**执行了两个不同的promise*/如果你觉得逻辑太复杂,请至少记住一点,OnceInit封装的PromiseFunction永远不会同时执行两次。此外,once-init还提供了其他的API来满足更多的需求,不过以上是它的主要功能。有关更多信息,请参见once-init的github。帮助我还将发布Vue3-CompositionApi的一个版本。(准备中)exportabstractclassRefOnceInitextendsOnceInit[,G>{loading=ref(false);protectedabstractfactory(raw:G,observe:Ref):void;constructor(defaultValue?:T){constrefed=ref();refed.value=defaultValue;超级(参考);this.onLoading((event)=>{this.loading.value=event;});}}所以RefOnceInit是一个响应对象。对于OnceInit类,请查看源代码。请求完成后,可能会导致页面UI发生变化。]