有梦想,有干货,微信搜索【大千世界】关注这位大清早还在洗碗的洗碗智慧。本文已收录到GitHubhttps://github.com/qq449245884/xiaozhi,里面有完整的测试站点、资料和我的一线厂商访谈系列文章。这是《用组合编写更好的代码》的第4篇文章,上一篇:Vue3,使用组合写出更好的代码(1/4)Vue3,使用组合写出更好的代码:灵活的参数(2/4)Vue3,使用Composition写出更好的代码代码:动态返回(3/4)如果允许异步代码正常工作,可以大大简化我们的代码。然而,处理这种额外的复杂性,尤其是使用Compatible时,可能会令人困惑。这篇文章介绍了没有等待的异步模式。这是一种在组合中编写异步代码的方法,没有通常令人头疼的问题。无需等待的异步使用组合API编写异步行为有时会很麻烦。所有异步代码必须在设置函数的末尾出现在任何反应代码之后。如果你不这样做,它会干扰你的反应。当设置函数到达await语句时,它将返回。一旦它返回,组件就会被挂载,应用程序将照常执行。在await之后定义的任何反应性,无论是计算的、观察者的还是其他的,都还没有被初始化。这意味着在await之后定义的计算属性首先不会被模板使用。相反,它仅在异步代码完成并且设置函数完成执行后才存在。然而,有一种方法可以编写异步组件,可以在任何地方使用而没有这些麻烦。constcount=ref(0);//这种异步数据获取不会干扰我们的响应能力const{state}=useAsyncState(fetchData());constdoubleCount=computed(()=>count*2);实现没有await的异步模式,为了实现这个模式,我们将同步挂起所有的反应值。每当异步代码完成时,这些值将被异步更新。首先,我们需要准备好我们的状态并返回它。我们将使用null值进行初始化,因为我们还不知道该值是什么。导出默认useMyAsyncComposable(promise){conststate=ref(null);returnstate;}其次,我们创建一个等待我们承诺的方法,然后将结果设置为状态:constexecute=async()=>{state.value=awaitpromise;}每当这个promise返回时,它就会主动更新我们的状态。现在我们只需要将这个方法添加到组合中。导出默认useMyAsyncComposable(promise){conststate=ref(null);//添加执行方法...constexecute=async()=>{state.价值=等待承诺;}//...并执行它!执行();returnstate;}我们在从useMyAsyncComposable方法返回之前调用了执行函数。但是,我们没有使用await关键字。当我们在execute方法中停止并等待promise时,执行流程立即返回到useMyAsyncComposable函数。然后它继续执行execute()语句并从可组合项返回。导出默认useMyAsyncComposable(promise){conststate=ref(null);constexecute=async()=>{//2.等待promise执行完成state.value=awaitpromise//5.一段时间后...//Promise完成,状态更新//execute已执行}//1.执行`execute`方法execute();//3.await将控制返回到这一点。//4.返回状态并继续执行“setup”方法returnstate;}promise在后台执行,因为我们没有等待它,所以它不会中断setup函数中的流程。我们可以将这个可组合项放置在任何地方,而不会影响响应能力。让我们看看VueUse中的一些组合是如何实现这种模式的。useAsyncStateuseAsyncState允许我们在任何地方执行任何异步方法并获得响应更新的结果。const{state,isLoading}=useAsyncState(fetchData());查看源代码时,您可以看到它实现了这个模式,但具有更多功能和更好地处理边缘情况。这是useAsyncState的简化版本:exportfunctionuseAsyncState(promise,initialState){conststate=ref(initialState);constisReady=ref(false);constisLoading=ref(false);常量错误=参考(未定义);异步函数执行(){error.value=undefined;isReady.value=false;isLoading.value=true;尝试{常量数据=等待承诺;state.value=数据;isReady.value=true;}catch(e){错误.value=e;}isLoading.value=false;}执行();return{state,isReady,isLoading,error,};}这个可组合系统还返回isReady,它告诉我们数据何时被提取。我们还得到isLoading和error来跟踪我们的加载和错误状态。现在来看另一个可组合项,我认为它有一个令人着迷的实现。如果向useAsyncQueue传递一组承诺函数给useAsyncQueue,它将按顺序执行每个函数。因此,在开始下一个任务之前,它会等待上一个任务完成。为了更加灵活,将其上一个任务的结果作为输入传递给下一个任务。const{result}=useAsyncQueue([getFirstPromise,getSecondPromise]);下面是官网的例子:constgetFirstPromise=()=>{//创建我们的第一个promisereturnnewPromise((resolve)=>{setTimeout(()=>{resolve(1000);},10);});};constgetSecondPromise=(result)=>{returnnewPromise((resolve)=>{setTimeout(()=>{resolve(1000+result);},20);});};const{activeIndex,result}=useAsyncQueue([getFirstPromise,getSecondPromise]);即使是异步执行代码,我们也不需要使用await。可组合程序甚至在内部也不使用await。相反,我们“在后台”执行这些承诺,并让结果被动更新。让我们看看这种组合是如何工作的。//初始化一些默认值constinitialResult=Array.from(newArray(tasks.length),()=>({state:promiseState.pending,data:null,});//将默认值改为responsiveconstresult=reactive(initialResult);//声明一个响应式下标constactiveIndex=ref(-1);主要功能由一个reduce支持,它一个一个处理每个功能tasks.reduce((prev,curr)=>{returnprev.then((prevRes)=>{if(result[activeIndex.value]?.state===promiseState.rejected&&interrupt){onFinished();return;}returncurr(prevRes).then((currentRes)=>{updateResult(promiseState.fulfilled,currentRes);activeIndex.value===tasks.length-1&&onFinished();returncurrentRes;})}).catch((e)=>{updateResult(promiseState.rejected,e);onError();returne;})},Promise.resolve());Reduce方法有点复杂,我们拆开来看一下:tasks.reduce((prev,curr)=>{//...},Promise.resolve());然后,开始处理每个任务。这是通过在先前的承诺之上链接一个.then来完成的。如果承诺被拒绝,则提前中止并返回。if(result[activeIndex.value]?.state===promiseState.rejected&&interrupt){onFinished();return;}如果没有提前终止,执行下一个任务并传递上一个promise的结果。我们还调用了updateResult方法,将其添加到复合返回的结果数组中returncurr(prevRes).then((currentRes)=>{updateResult(promiseState.fulfilled,currentRes);activeIndex.value===tasks.length-1&&onFinished();返回currentRes;});如您所见,此可组合项实现了AsyncWithoutAwait模式,但该模式只是整个可组合项的几行代码。所以它不需要很多额外的工作,只要记住把它放到位就可以了总结如果我们使用AsyncWithoutAwait模式,我们可以更轻松地使用异步组合。这种模式允许我们将异步代码放在我们想要的地方,而不用担心破坏响应能力。编辑过程中可能存在的BUG无法实时获知。之后为了解决这些bug,花费了大量的时间在日志调试上。顺便推荐一个好用的BUG监控工具Fundebug。作者:MichaelThiessen译者:小智来源:vuemastery原文:https://www.vuemastery.com/bl...交流有梦想,有干货,微信搜索【大招天下】关注这个我在还在清晨洗碗洗碗的智慧。本文已收录到GitHubhttps://github.com/qq449245884/xiaozhi,里面有完整的测试站点、资料和我的一线厂商访谈系列文章。
