循环依赖
在复杂的状态中,有时会不经意间会产生循环依赖,这是响应式状态管理中的一个常见问题。
AutoStore
提供了相应的循环依赖检测
和调试跟踪能力
功能,帮助开发者发现和解决循环依赖问题。
同步循环依赖检测
构建AutoStore
时如果存在循环依赖,会抛出异常,开发者可以通过异常信息快速定位问题。
以下示例中就存在循环依赖,构建store
时会抛出异常。
异步循环依赖检测
异步循环依赖就比较麻烦,无法像同步循环一样构建时自动检测。因为异步计算属性的计算函数是异步的,很容易在多个异步计算时形成很复杂的循环调用链。
AutoStore
提供了cycleDetect
扩展,用来帮助检测异步计算属性的循环依赖。但是由于进行循环依赖检测需要一定的成本开销,
所以该功能是作为一个扩展,需要手动安装。
启用检测
ts
import { installCycleDetectExtend } from '@autostorejs/devtools'
installCycleDetectExtend({
onDetected:(paths)=>{
console.error("发现循环依赖:",paths)
return 'disable'
}
})
示例
由于a
,b
存在循环依赖,内部会忽略a
,b
的计算,导致a
,b
的值为无法计算。
- 在控制台可以发现
发现循环依赖: 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 代表忽略,其他触发错误。 |