你在正确的轨道上,我会尽力给你你所说的额外推动:
如果你想要松耦合,pub-sub 是一个不错的选择。
但是,您实际上并不需要那个“中介”,理想情况下,每个模块都应该是自治的并封装自己的逻辑。
这是通过以下方式完成的:每个模块都依赖于 pubsub 服务,订阅所有相关事件并对其采取行动。每个模块还发布可能与其他模块相关的事件(一分钟内的代码示例,请耐心等待)。
我认为您在这里可能缺少的一点是使用事件的模块几乎永远不会只是简单的模型。他们将有一些逻辑,并且可以也持有一个模型(他们在接收事件时更新)。
因此,您更有可能拥有dataLoaderModule,而不是dataModule,它会在他完成加载后发布数据模型(例如{data: 3})。
您设置的另一个重要要求是在避免全局实例变量的同时共享数据 - 这是一个非常重要的概念,也是朝着正确方向迈出的一步。您在解决方案中错过的是 - 依赖注入或至少一个允许定义依赖关系的模块系统。
您知道,拥有一个事件驱动的应用程序并不一定意味着每一段代码都应该使用事件进行通信。应用程序配置模型或实用程序服务绝对是我会注入的东西(当使用 DI 时,比如在 Angular 中)、require(当使用 AMD/CommonJS 时)或导入(当使用 ES6 模块时)。
(即,而不是使用事件与实用程序通信)。
在您的示例中,不清楚 configModule 是静态应用程序配置还是我可以从 UI 调整的某个旋钮。如果它是一个静态应用配置 - 我会注入它。
现在,让我们看一些例子:
假设如下:
- 我们有一个
dataLoaderModule,而不是dataModule
-
configModule 是一个静态的 configuration 模型。
- 我们使用的是 AMD 模块(而不是我更喜欢的 ES6 模块),因为我看到您坚持只使用 ES5 功能(我看不到任何类或 const)。
我们会:
data-loader.js(又名 dataLoaderModule)
define(['pubsub'], function (pubsub) {
// ... load data using some logic...
// and publish it
pubsub.publish('data-loaded', {data: 3});
});
configuration.js(又名 configModule)
define([], function () {
return {factor: 2};
});
display.js(又名 displayModule)
define(['configuration', 'pubsub'], function (configuration, pubsub) {
var displayModule = {
display: function (data, factor) {
console.log(data * factor);
}
};
pubsub.subscribe('data-loaded', function (data) {
displayModule.display(data, configuration.factor);
});
});
就是这样。
您会注意到我们这里没有全局变量(甚至没有 pubsub),而是需要(或注入)我们的依赖项。
您可能会问:“如果我的意思是让我的配置从 UI 更改呢?”,让我们也看看:
在这种情况下,我宁愿将 configModule 重命名为 settingsDisplayModule(遵循您的命名约定)。
另外,在更真实的应用中,UI 模块通常会包含一个模型,所以我们也这样做。
我们也将它们称为“视图”而不是“显示模块”,我们将拥有:
data-loader.js(又名 dataLoaderModule)
define(['pubsub'], function (pubsub) {
// ... load data using some logic...
// and publish it
pubsub.publish('data-loaded', {data: 3});
});
settings-view.js(又名 settingsDisplayModule,又名配置)
define(['pubsub'], function (pubsub) {
var settingsModel = {factor: 2};
var settingsView = {
display: function () {
console.log(settingsModel);
// and when settings (aka config) changes due to user interaction,
// we publish the new settings ...
pubsub.publish('setting-changed', settingsModel);
}
};
});
data-view.js(又名 displayModule)
define(['pubsub'], function (pubsub) {
var model = {
data: null,
factor: 0
};
var view = {
display: function () {
if (model.data && model.factor) {
console.log(model.data * model.factor);
} else {
// whatever you do/show when you don't have data
}
}
};
pubsub.subscribe('data-loaded', function (data) {
model.data = data;
view.display();
});
pubsub.subscribe('setting-changed', function (settings) {
model.factor = settings.factor;
view.display();
});
});
就是这样。
希望对你有帮助:)
如果没有 - 评论!