一个复杂的包含resource场景的依赖,加载过程无法完成
errorrik opened this issue · 1 comments
errorrik commented
foo -> bar -> tpl!x
empty
如果tpl!x
已经预先require并ready时
- 当
require(['foo'],callback)
时,callback被调用,但是未来foo模块将不存在 - 当
require(['foo', 'empty'],callback)
时,callback不被调用
原因是因为,modAutoDefine会对每个需要自动定义的模块进行modPrepare、modUpdatePreparedState、modTryInvoke调用。modUpdatePreparedState中,会尝试调用其依赖模块的modPrepare。如果模块包含resource依赖,modPrepare中会在尝试在resource加载完后重新调起modAutoDefine。当resource当前已经处于ready状态时,这个过程会马上发起。从而导致一个运行过程中,同一个模块的modUpdatePreparedState被重入。而modUpdatePreparedState中,对模块状态的写入没有做判断,从而导致模块状态可能从defined回退到prepared。
过程如下:
script onload -> modAutoDefine -> modPrepare(foo) -> modUpdatePreparedState(foo) -> modPrepare(bar) -> requireResource -> modAutoDefine -> modPrepare(foo) -> modUpdatePreparedState(foo) -> modTryInvoke(foo) -> modTryInvoke(foo)
由于:
- resource加载完后重新调起modAutoDefine是合理的。因为resource加载可能是异步过程。所以这里不能干掉
- modUpdatePreparedState不可重入控制的话,增加代码量会多一些
所以,采用解决方案为:modUpdatePreparedState中,对模块状态的写入做判断
if (!modIs(id, MODULE_PREPARED) {
mod.state = MODULE_PREPARED;
}