gpt4 book ai didi

javascript - Ember.js Application.inject 循环依赖

转载 作者:行者123 更新时间:2023-11-29 22:02:39 25 4
gpt4 key购买 nike

你好,我用 ember.js 构建我的应用程序已经用了大约 2 周时间,是时候将我的项目布局整合到最终形状中了。为此,我开始研究使用 Ember 的注册/注入(inject)机制,而不是仅仅创建全局单例并将它们附加到我的 App 对象(有关 Ember 中依赖注入(inject)的精彩描述,请参阅 here)

我陷入了标准依赖注入(inject)困境 - 循环引用。

比方说,我有两个类似管理器的类,我需要在整个应用程序中使用它们。我们称它们为 AuthManager 和 DataManager。

App.AuthManager = Ember.Object.extend({
logIn: function (user) {
var promise = this.dataManager.post("/session/new", user);
//...
}
});

App.DataManager = Ember.Object.extend({
getJSON: function (url) {
if (!this.authManager.get("isLoggedIn")) {
return false;
}
//...
}
});

因此,如您所见,dataManager 需要访问 authManager,反之亦然。我对解决方案的天真看法是这样的:

App.initializer({
name: "dataManager",

initialize: function (container, application) {
application.register("my:dataManager", application.DataManager);
application.inject("my:authManager", "dataManager", "my:dataManager");
}
});

App.initializer({
name: "authManager",

initialize: function (container, application) {
application.register("my:authManager", application.AuthManager);
application.inject("my:dataManager", "authManager", "my:authManager");
}
});

可以预见,这会导致死循环。我希望依赖注入(inject)系统会尝试一些狡猾的杂耍,就像节点的 require 那样,但没有。

我试过:

  • my:authManager 注册后,将第一个注入(inject)移动到第二个初始化器中。
  • 在前两个之后将第一个注入(inject)移动到它自己的初始化器中
  • 将这些的任意组合放入链接文章中的 Ember.onLoad('Ember.Application', ...)

不幸的是,我尝试的一切都以堆栈溢出结束(双关语:-))。

我错过了什么吗?这方面的文档非常少。当然,我总是可以在“官方”注入(inject)后手动查找实例,但我希望有一些更优雅的解决方案。

最佳答案

你肯定有循环依赖,如果你使用不同的语言,我会告诉你使用控制反转模式,但使用你的问题和容器有点困难。

方案一

如果您可以将它们添加到诸如 manager 之类的 namespace 下,那么这里有一个解决方案(它是紧密耦合的,但代码已经紧密耦合,几乎足以让它们成为一起或在另一个上混入)。

App.Manager = Ember.Object.extend({
init: function(){
// late fake injection
this.authManager.dataManager = this.dataManager;
this.dataManager.authManager = this.authManager;
}
});


App.initializer({
name: "manager",
after:['dataManager', 'authManager'],

initialize: function (container, application) {
application.register("my:manager", application.Manager);
application.inject("my:manager", "dataManager", "my:dataManager");
application.inject("my:manager", "authManager", "my:authManager");
application.inject("controller", "manager", "my:manager");
application.inject("route", "manager", "my:manager");
}
});

App.initializer({
name: "dataManager",

initialize: function (container, application) {
application.register("my:dataManager", application.DataManager);
}
});

App.initializer({
name: "authManager",

initialize: function (container, application) {
application.register("my:authManager", application.AuthManager);
}
});

还有一个例子:

http://emberjs.jsbin.com/mopaquko/2/edit

解决方案2

另一方面,这会在每个路由/ Controller 上创建一个新实例。如果你只需要一个实例。您可以这样做,更容易并且不需要命名空间。

App.initializer({
name: "joinManagers",
after:['dataManager', 'authManager'],

initialize: function (container, application) {
var dataManager = container.lookup('my:dataManager'),
authManager = container.lookup('my:authManager');

authManager.dataManager = dataManager;
dataManager.authManager = authManager;

application.register("my:jointDataManager", dataManager, {instantiate:false});
application.register("my:jointAuthManager", authManager, {instantiate:false});
application.inject("controller", "dataManager", "my:jointDataManager");
application.inject("controller", "authManager", "my:jointAuthManager");
application.inject("route", "dataManager", "my:jointDataManager");
application.inject("route", "authManager", "my:jointAuthManager");
}
});


App.initializer({
name: "dataManager",

initialize: function (container, application) {
application.register("my:dataManager", application.DataManager);
}
});

App.initializer({
name: "authManager",

initialize: function (container, application) {
application.register("my:authManager", application.AuthManager);
}
});

http://emberjs.jsbin.com/mopaquko/3/edit

方案三

正如所指出的,Ember 的容器默认创建单例,您可以急切地创建副本,然后允许 ember 仍然基于原始命名空间进行解析。

App.initializer({
name: "joinManagers",
after:['dataManager', 'authManager'],

initialize: function (container, application) {
var dataManager = container.lookup('my:dataManager'),
authManager = container.lookup('my:authManager');

authManager.dataManager = dataManager;
dataManager.authManager = authManager;

application.inject("controller", "dataManager", "my:dataManager");
application.inject("controller", "authManager", "my:authManager");
application.inject("route", "dataManager", "my:dataManager");
application.inject("route", "authManager", "my:authManager");
}
});


App.initializer({
name: "dataManager",

initialize: function (container, application) {
application.register("my:dataManager", application.DataManager);
}
});

App.initializer({
name: "authManager",

initialize: function (container, application) {
application.register("my:authManager", application.AuthManager);
}
});

http://emberjs.jsbin.com/mopaquko/7/edit

关于javascript - Ember.js Application.inject 循环依赖,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/22736022/

25 4 0
Copyright 2021 - 2024 cfsdn All Rights Reserved 蜀ICP备2022000587号
广告合作:1813099741@qq.com 6ren.com