简体   繁体   English

从RequireJS开始,模块之间的通信

[英]Starting with RequireJS, communication between modules

I am an ActionScript 3 developer who is just making his first way in building a large-scale JavaScript app. 我是一名ActionScript 3开发人员,他只是在构建大型JavaScript应用程序方面迈出了第一步。 So I understand modules and understand that AMD is a good pattern to use. 因此,我了解模块并了解AMD是一个很好的使用模式。 I read about RequireJS and implemented it. 我了解了RequireJS并实现了它。 However, what I still don't understand is how to achieve Cross-Module communication. 但是,我仍然不了解如何实现跨模块通信。 I understand that there should be some kind of mediator... I read articles and posts and still couldn't understand how to implement it simply. 我知道应该有某种中介者...我阅读了文章和帖子,但仍然不明白如何简单地实现它。 Here is my code, simplified: 这是我的代码,简化了:

main.js main.js

require(["Player", "AssetsManager"], function (player, manager) {
    player.loadXML();
});

Player.js Player.js

define(function () {
    function parseXml(xml)
    {
        // NOW HERE IS THE PROBLEM -- how do I call AssetsManager from here???

        AssetsManager.queueDownload($(xml).find("prop").text());
    }

    return {
        loadXML: function () {
            //FUNCTION TO LOAD THE XML HERE, WHEN LOADED CALL parseXml(xml)
        }

    }

});

AssetsManager.js AssetsManager.js

define(function () {
    var arrDownloadQueue = [];

    return {
        queueDownload: function(path) {
            arrDownloadQueue.push(path);
        }
    }
});

Any "for dummies" help will be appreciated :) Thank you. 任何“傻瓜”帮助将不胜感激:)谢谢。

To load up modules from another modules that you define() , you would simply set the first parameter as an array, with your module names in it. 要从您define()另一个模块中加载模块,只需将第一个参数设置为数组,并在其中包含模块名称即可。 So let's say, in your code, you wanted to load Player.js into AssetsManager.js , you would simply include the string Player in the array. 假设我们要在代码Player.js AssetsManager.js加载到AssetsManager.js ,只需将字符串Player包含在数组中即可。

This is simply possible because define 's abstract implementation is equivalent to require , only that the callback passed to define expects a value to be returned, and that it will add a "module" to a list of dependencies that you can load up. 这完全是可能的,因为define的抽象实现等效于require ,只是传递给define的回调期望返回一个值,并且它将在要加载的依赖项列表中添加“模块”。

AssetsManager.js AssetsManager.js

define(['Player'], function (player) {
    //... Your code.
});

However, if I can add to it, I personally prefer the use of require inside of the callback passed to define to grab the dependency that you want to load, instead of passing parameter to the callback. 但是,如果可以添加它,我个人更喜欢在传递的回调内部使用requiredefine以获取要加载的依赖项,而不是将参数传递给回调。

So here's my suggestion: 所以这是我的建议:

define(['Player'], function () {
    var player = require('Player');
});

And this is because it's much more in tune with CommonJS . 这是因为它与CommonJS更加协调

And this is how main.js would look like formatted to be more CommonJS-friendly: 这就是main.js格式,看起来对CommonJS更友好:

require(["Player", "AssetsManager"], function () {
    var player = require('Player');
    var manager = require('AssetsManager');
    player.loadXML();
});

But the CommonJS way of doing things is just a personal preference. 但是CommonJS的处事方式只是个人喜好。 My rationale for it is that the order in which you input the dependency names in the array might change at any time, and i wouldn't want to have to step through both the array and the parameters list. 我的理由是,您可以在任何时候更改在数组中输入依赖项名称的顺序,并且我不想同时浏览数组和参数列表。

Another rationale of mine (though, it's just pedantic), is that I come from the world of Node.js, where modules are loaded via require() . 我的另一个基本原理(尽管这很简单)是我来自Node.js的世界,那里的模块是通过require()加载的。

But it's up to you. 但这取决于你。

(This would be a reply to skizeey's answer, but I don't have enough reputation for that) (这是对skizeey的回答,但我对此没有足够的声誉)

Another way of solving this problem without pulling in Player's AssetManager dependency via require is to pass the AssetManager instance that main.js already has around. 解决此问题而无需通过require引入Player的AssetManager依赖关系的另一种方法是传递main.js已经拥有的AssetManager实例。 One way of accomplishing this might be to make Player's loadXML function accept an AssetManager parameter that then gets passed to parseXml, which then uses it. 实现此目的的一种方法可能是使Player的loadXML函数接受AssetManager参数,然后将其传递给parseXml,然后使用它。 Another way might be for Player to have a variable to hold an AssetManager which gets read by parseXml. 另一种方法是让Player具有一个变量,以保存由parseXml读取的AssetManager。 It could be set directly or a function to store an AssetManager in the variable could be used, called say, setAssetManager. 可以直接设置它,也可以使用将AssetManager存储在变量中的函数,称为setAssetManager。 This latter way has an extra consideration though - you then need to handle the case of that variable not being set before calling loadXml. 但是,后一种方式需要额外考虑-在调用loadXml之前,您需要处理未设置该变量的情况。 This concept is generally called "dependency injection". 这个概念通常称为“依赖注入”。

To be clear I'm not advising this over using AMD to load it in. I just wanted to provide you with more options; 需要明确的是,我不建议使用AMD来加载它。我只是想为您提供更多选择; perhaps this technique may come in handier for you when solving another problem, or may help somebody else. 也许在解决另一个问题时,该技术可能对您比较方便,或者可能对其他人有所帮助。 :) :)

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM