Javascript Requirejs与异步和循环依赖

Javascript Requirejs与异步和循环依赖,javascript,asynchronous,requirejs,circular-dependency,appjs,Javascript,Asynchronous,Requirejs,Circular Dependency,Appjs,我目前正在开发一个web应用程序来编辑一些自定义文件格式—一个提供编辑配置文件界面的小型编辑器。 这个应用程序的一个关键元素是一个名为FileReader的对象,它是一个包装器,根据检测到的配置文件类型触发正确的接口。这样我就产生了一个新的FileReader src-src,它是一个url或blob,并且保持干净 一旦检索到配置文件的类型,包装器将检查是否有与其关联的接口,并简单地使用它。每个不同配置类型的每个接口都在单独的JS文件中定义。一旦包装器完全加载,我就钩住所有事件,应用程序开始执行

我目前正在开发一个web应用程序来编辑一些自定义文件格式—一个提供编辑配置文件界面的小型编辑器。 这个应用程序的一个关键元素是一个名为FileReader的对象,它是一个包装器,根据检测到的配置文件类型触发正确的接口。这样我就产生了一个新的FileReader src-src,它是一个url或blob,并且保持干净

一旦检索到配置文件的类型,包装器将检查是否有与其关联的接口,并简单地使用它。每个不同配置类型的每个接口都在单独的JS文件中定义。一旦包装器完全加载,我就钩住所有事件,应用程序开始执行

以下是我与相关元素一起使用的HTML框架:

<!doctype html>
<html><head></head>
<body>
    <div id="UI"></div>
    <script src="js/fileReader/fileReader.js" >App.FileReader = function(){ ... }</script>
    <script src="js/fileReader/configType1.js" >App.FileReader.registerFileType("config1",object)</script>
    <script src="js/fileReader/configType2.js" >App.FileReader.registerFileType("config2",object)</script>
    <script src="js/fileReader/configType3.js" >App.FileReader.registerFileType("config3",object)</script>
    <script src="js/main.js" >App.run();</script>
</body>
</html>
fileReader.js:

define(function () {

    ...

    return FileReader ;

});
define(["require"],function ( require ) {

    ...

    require(["config1","config2","config3"],
    function(){
        //occurs asynchronously, after the App.run() is triggered because of the synchronous return 
        callback(FileReader) ; //unfortunately I did not find any callback of this sort
                               //if it existed I could asynchronously find the list of the modules in the directory, load the them, and only then fire this fictive "ready" event
    }

    return FileReader ; //the first return occurs synchronously, so before the the fileReader is ready : modules are missing

});
config1.js:

define(['FileReader'], function ( FileReader ) {

    var Interface = ... ;

    ...

    App.FileReader.registerFileType("config1",Interface)

    return FileReader ;

});
app.js:

define(['FileReader'], function ( FileReader ) {

    var App = function(){} ;

    App.run = function(){ FileReader.openFile( ... ) ; ... } ;

    return App ;

});
我的问题是什么? 为了确保FileReader对象包含正确的接口对象,我首先手动强制requirejs加载所有与FileReader相关的文件,然后加载主应用程序文件。这样,一旦应用程序对象请求FileReader对象,它就已经包含注册的正确接口。 我想要达到的只是要求 主文件中的/core/app /core/app文件中的/fileReader 然后在第一次加载期间,如果它可以加载fileReader文件中的配置类型模块,注册所有内容,然后返回答案,那就好了

我尝试的是:在FileReader中

fileReader.js:

define(function () {

    ...

    return FileReader ;

});
define(["require"],function ( require ) {

    ...

    require(["config1","config2","config3"],
    function(){
        //occurs asynchronously, after the App.run() is triggered because of the synchronous return 
        callback(FileReader) ; //unfortunately I did not find any callback of this sort
                               //if it existed I could asynchronously find the list of the modules in the directory, load the them, and only then fire this fictive "ready" event
    }

    return FileReader ; //the first return occurs synchronously, so before the the fileReader is ready : modules are missing

});

那么,在配置类型文件和主文件读取器之间以某种循环依赖关系加载此类模块的最佳方式是什么呢?如果我想强制它是异步的,这样我就可以读取config type目录中的可用内容,那该怎么办?有了简单的HTML脚本列表,它们按正确的顺序加载,我可以轻松访问模块列表,现在我想确保在应用程序启动之前一切都准备好了。

在我看来,您可以将记录可用文件类型的功能打包到一个新模块中,可能名为FileTypeRegistry。因此,您的配置文件可能如下所示:

define(['FileTypeRegistry'], function ( FileTypeRegistry ) {

    var Interface = ... ;

    ...

    FileTypeRegistry.registerFileType("config1", Interface);    
});
这些模块不需要返回值。registerFileType只是在注册表中注册一个类型

FileReader.js可以包含:

define(["FileTypeRegistry", "config1", "config2", "config3"], function ( FileTypeRegistry ) {

    var FileReader = {};

    var FileReader.openFile = function (...) {
        var impl = FileTypeRegister.getFileTypeImplementation(...);
    };

    return FileReader;
});

getFileTypeImplementation检索以前基于类型名称注册的接口的实现。

Louis的回答很有趣,但它只是解决了创建新模块的问题,即使它将依赖项放在了正确的上下文中,我试图搜索一些真正的异步模块定义,而不仅仅是加载

我最终能想到的最好办法是编辑require.js源文件,添加我期望的行为。我注册了一个新的处理程序,它具有一种特殊的依赖行为,如require或exports,称为delay,它为模块定义提供了回调函数:

基本上是这样的:

define(["delay"], function ( delay ) {

    var Module = ... ;

    setTimeout(function(){ //Some asynchronous actions
        delay(Module) ; //This does actually returns the Module's value and triggers the "defined" event.
                        //It's actually transparent so the other modules just "feel" that the network's load time was a bit longer.
    },1000);

    return Module ; //This does not do anything because delay is active

});
由于这个异步定义,我现在可以通过异步请求扫描目录,然后透明地加载所有模块。 修改仅代表约10行,因此如果有人感兴趣,我将其张贴在那里:


显然,这不是异步导出的第一个请求,但仍在讨论中,因此我将其用于个人项目。

我能够编辑requirejs源代码,以更好地支持我需要的内容,所以现在一切正常。感谢您的回复: