在GWT Code Splitting Dev Guide及其中建议的模块模式的上下文中定义了排除代码片段,我理解第一次调用静态Module.createAsync(final ModuleClient client)
然后Module
内的代码下载了类,后续对此静态函数的调用将不会再次下载相同的代码片段。
该模式进一步建议缓存INSTANCE
类的Module
以用于“对于在模块之后明确加载的任何代码”。
所以我的问题是:
从初始片段第一次调用后,每次调用Module.createAsync(final ModuleClient client)
是否都会调用服务器来检查代码片段是否需要下载?或者是否在没有任何服务器调用开销的情况下调用onSuccess()
?
初始片段中的以下代码是否导致Module
代码成为初始下载的一部分(即,不是排除片段)?
>
if (INSTANCE == null)
Module.createAsync(new ModuleClient()
{
@Override
public void onUnavailable(Throwable reason)
{
// Action in case of failure
}
@Override
public void onSuccess(Module instance)
{
instance.showBigComplicatedStuff();
}
});
else
INSTANCE.showBigComplicatedStuff();
换句话说:
初始片段子句中是否存在INSTANCE.showBigComplicatedStuff();
会导致包含Module
的{{1}}代码成为初始片段的一部分,还是会导致showBigComplicatedStuff()
因为Module
在new Module()
内(在Module.createAsync
内)被调用,因此无论如何都是在一个独占片段中?
仅当GWT.runAsync
有助于减少对服务器的不必要的异步调用时,这种第一次调用Module.createAsync
的模式是什么? (同样,我了解那些最终的服务器调用不会再次下载相应的INSTANCE == null
片段。)
答案 0 :(得分:3)
您拥有的代码不完整 - 为什么您拥有INSTANCE
和instance
并不明显,如果INSTANCE是作为Module.createAsync的一部分生成的公共字段,则还可以执行其他操作填充它?我会尝试自己回答这两个问题,指出我在路上做出的任何假设
假设INSTANCE类型的对象永远不可能在GWT.runAsync
之外创建,实例方法showBigComplicatedStuff
除非已加载分割点,否则无法执行任何操作(因此至少有一个实例已经创建) - 编译器足够聪明,可以解决这个问题。但是,
空检查是没有意义的,正是你提到的原因 - 如果你明白没有服务器调用去获取新的GWT.runAsync
片段,那么你认为异步服务器调用是什么发生在GWT.runAsync
内?如果代码已下载且无需再次下载,则无需下载。
自页面加载以来第二次运行GWT.runAsync
没有任何开销。如果正确实现了缓存,甚至在页面加载后第一次点击它再次应该是便宜/免费的(这意味着服务器不会被再次击中,但仍有费用将JS解析为内存)。
因为GWT.runAsync
在加载后没有服务器调用开销(因此INSTANCE
不是null
),所以您不必担心它。 GWT会注意到它已经拥有了所需的代码,并且不会再尝试下载它。
即使没有所谓的完美&#39;缓存,这种行为都将成立。如果您正在设置缓存标头以便将<hashname>.cache.*
文件缓存一年,那么第二次加载模块或分割点时,它将继续使用相同的本地结果而不会有网络流量。如果没有完美的缓存,但磁盘上的文件仍然相同,重新加载应用程序将导致304 Not Modified
- 不是免费的,但不像再次下载那样昂贵。
GWT应用程序(使用其中一个标准链接器)以appname.nocache.js
文件开头 - 此文件包含上面提到的<hashname>
字符串,只有在代码更改时才会更改,因此不得高速缓存以便可以发生代码更改,客户端立即看到更改。然后下载或读取给定属性集的初始片段(即&#39;哪个浏览器&#39; *&#39;哪个区域设置&#39; *&#39;哪些形式因素&#39;等)缓存为<hashname>.cache.js
,然后当命中给定的分裂点<N>
时,分割点将被提取为deferredjs/<hashname>/<N>.cache.js
。
尽管如此,Module.createAsync
事物背后的理论是异步工厂,所以你当然可以按照你描述的方式使用它。在这种情况下,如果只有一个实例很重要,我可能有一个getOrCreateAsync
来执行模块类中的单例位 - 只要该类负责创建实例并提供它,它也可以总是提供它。这实际上取决于您如何使用实例,它包含的内容等等。