处理循环依赖

Handling circular dependencies

本文关键字:依赖 循环 处理      更新时间:2023-09-26

我相信下面四种方法都可以工作,但我不清楚为什么有人会使用前三种方法,仅仅因为它的代码更多。然而,第一个(也是最冗长的)是在RequireJS文档中给出的。

define "circular1", ["example1"], -> "circular1"
define "circular2", ["example2"], -> "circular2"
define "circular3", ["example3"], -> "circular3"
define "circular4", ["example4"], -> "circular4"
#1
define "example1", ["require", "circular1"], (require, circular) ->
  alert "example1 Before: " + circular
  circular = require "circular1"
  alert "example1 After: " + circular
#2
define "example2", ["require"], (require) ->
  alert "example2 Before: " + circular
  circular = require "circular2"
  alert "example2 After: " + circular
#3
define "example3", ["circular3"], (circular) ->
  alert "example3 Before: " + circular
  circular = require "circular3"
  alert "example3 After: " + circular
#4
define "example4", [], ->
  alert "example4 Before: " + circular
  circular = require "circular4"
  alert "example4 After: " + circular
require ["example1"], ->
require ["example2"], ->
require ["example3"], ->
require ["example4"], ->
  • 如果circularDependency是未定义的,直到你做显式的require,麻烦把它包括在定义中的意义是什么(#1 &# 3) ?
  • 如果require总是作为第一个脚本加载全局可用,为什么要传递它?这仅仅是代码清晰度的问题,即,它只是在代码的顶部提供所有依赖关系的简洁快照(因为您可能直到很久以后才真正得到显式require ?或者它是否有一些真正的影响RequireJS如何优化取决于它是否包含在define ?

我不想使用这些变化中的任何一个,如果它对我的软件有负面影响,只是因为它"工作"。"

当RequireJS将每个模块作为一个单独的文件加载,而不是将它们捆绑在一起时,情况就不同了。在依赖项列表中指定该模块会告诉RequireJS,它需要在调用该模块的函数之前加载该模块。由于require是同步的,它不会尝试同步加载脚本,如果脚本尚未加载,则无法返回模块。由于require应该解析相对于要求模块的相对模块id,因此您需要使用它传递给您的require。所以:

  1. 第一种方法是正确的。它告诉RequireJS,如果模块还没有被加载,就加载它。如果circular最初是undefined,它可以很快用其他模块填充它。

  2. 第二种方式是不正确的。如果circular2没有加载,对require的调用将无法工作。它将正确地解析模块ID,因为它使用了给定的require

  3. 第三种方法是正确的在这种情况下,但是如果您传递给它一个相对模块ID,如./circular3,它将不工作。如果模块还没有被加载,它也会告诉RequireJS加载模块,这样您就不会遇到#2中的问题。唯一的区别是它使用全局require,它缺乏传递给工厂函数的require的上下文,所以如果你传递给它一个像./circular3这样的相对模块ID,它不知道相对于什么来解析它。

  4. 这种方法结合了#2和#3的不正确性。首先,它不能正确解析相对模块id。其次,即使它可以正确地解析相对id,它仍然不会加载尚未加载的模块。

如果你能保证circularN模块总是在exampleN模块需要它之前定义,那么是的,它将工作,但使用方法#1和#3确保它将工作,即使情况并非如此。