循环依赖
在复杂的状态中,有时会不经意间会产生循环依赖,这是响应式状态管理中的一个常见问题。
AutoStore提供了相应的循环依赖检测和调试跟踪能力功能,帮助开发者发现和解决循环依赖问题。
同步循环依赖检测
构建AutoStore时如果存在循环依赖,会抛出异常,开发者可以通过异常信息快速定位问题。
以下示例中就存在循环依赖,构建store时会抛出异常。
loading
异步循环依赖检测
异步循环依赖就比较麻烦,无法像同步循环一样构建时自动检测。因为异步计算属性的计算函数是异步的,很容易在多个异步计算时形成很复杂的循环调用链。
AutoStore提供了cycleDetect扩展,用来帮助检测异步计算属性的循环依赖。但是由于进行循环依赖检测需要一定的成本开销,
所以该功能是作为一个扩展,需要手动安装。
启用检测
ts
import { installCycleDetectExtend } from '@autostorejs/devtools'
installCycleDetectExtend({
onDetected:(paths)=>{
console.error("发现循环依赖:",paths)
return 'disable'
}
})示例
由于a,b存在循环依赖,内部会忽略a,b的计算,导致a,b的值为无法计算。
loading
- 在控制台可以发现
发现循环依赖: a->b->a.loading->a.timeout->a.retry->a.error->a.value->a.progress->b.loading->b.timeout->b.retry->b.error->b.value->b.progress->x的信息,这是循环依赖的路径。 onDetected回调函数返回disable代表当检测到循环依赖后,会禁用该计算属性,这样就可以避免循环依赖导致的问题。
基本原理
异步循环依赖检测比较复杂,特别是在异步计算属性中,很容易形成很复杂的循环调用链。
循环依赖检测的基本原理如下:
- 安装
cycleDetect扩展后,会对每个异步计算属性的run函数进行包装。 - 当计算属性第一次运行时,执行
store.wath记录侦听所有的get读操作事件。如果存在循环依赖,就会执行计算属性的run函数,从而可以收集到大量的get事件。 - 当侦听到指定
maxOperates数量的get事件后,进行分析,找出事件列表中的循环依赖路径即可。 - 然后执行
onDetected回调函数,由开发者决定如何处理:return 'disable': 代表禁用该计算属性。return 'ignore': 代表忽略- 其他会触发错误
配置参数
installCycleDetectExtend具有以下配置参数:
| 参数 | 类型 | 默认值 | 说明 |
|---|---|---|---|
maxOperates | number | 200 | 最大操作数,从开始运行计算函数后,当收集到此数量的操作事件后开如分析。 |
onDetected | (paths:string)=>'disable' | 'ignore' | void | - | 当检测到循环依赖时的回调函数,返回disable代表禁用该计算属性,返回ignore代表忽略,其他触发错误。 |