2

我正在使用看起来非常适合 DI 的东西,但它被添加到现有框架中,而该框架在编写时并未考虑到这一点。定义依赖项的配置来自后端模型。实际上,此时它还不是完整的配置,它基本上包含一个可用于确定特定视图是否可用的键。

我正在使用 require 所以依赖看起来像这样

// Dependency
define(['./otherdependencies'], function(Others) {
    return {
        dep: "I'm a dependency"
    };
});

现在注射器看起来像这样

// view/injector
define([
    './abackendmodel',
    './dependency'
], function(Model, Dependency) {
    return {
        show: function() {
            if (model.showDepency) {
                var dep = new Dependency();
                this.$el.append(dep);
            }
        }
    };
});

这与实际代码相差甚远,但重要的部分是 require 的工作方式。请注意,在注入器代码中,依赖项是必需的并在 show 方法中使用,但前提是模型表示应该显示它。问题是依赖项可能需要的其他东西在不应该显示时不可用。所以我真正想做的不是必须指定该依赖关系,除非它model.showDependency是真的。我想出了一些想法,但没有我喜欢的。

想法一个 基于该模型属性进行另一个异步要求调用。所以注射器看起来像这样。

// Idea 2 view/injector
define([
    './abackendmodel'
], function(Model) {
    var Dep1 = null;
    if (model.showDepedency) {
        require([
            './dependency'
        ], function(Dependency) {
            Dep1 = Dependency;
        });
    }
    return {
        show: function() {
            if (Dep1) {
                var dep = new Dep1();
                this.$el.append(dep);
            }
        }
    };
});

显然这有问题。如果在 async require 调用完成之前调用 show ,那么Dep1仍然为 null。所以我们并没有真正展示作为目标的依赖关系,显然在这种情况下会抛出 JS 错误。此外,我们仍在使用if我不喜欢的节目检查,但用例是依赖项可能存在也可能不存在,如果不需要它,我们只是不想要求它,所以我可能无法解决这个问题。还要记住,这model.showDependency实际上不是一个布尔值。它可以有多个值,这将需要不同的依赖项。为了简单地理解基本问题,我在这里将其剥离。

想法二 这不太稳固,即我认为这甚至行不通,但我考虑过使用 require config.path 的东西。我的想法基本上是有两个配置,以便'./dependency'指向不同的地方。问题在于,尽管model.showDependency配置的值是相同的,但需要配置,因此无法在运行时更改它。也许可以在这里完成一些魔术,例如定义单独的视图目录路径并使用工厂类型对象返回我们关心的对象,但因为这最终会导致在Idea中出现相同的异步行为,所以我不认为给我买任何东西(基本上是一样的)。

思路三 让依赖基于model.showDependency属性返回null。这可能是目前最好的解决方案。我仍然坚持一些ifs 但我认为这不会消失。这也可以防止调用初始化代码。

有更好的想法吗?

4

1 回答 1

1

为什么不尝试使用 Promise 来加载依赖项?

您有两种选择,具体取决于您的代码需要如何工作。

选项 1) 为模块 'view/injector' 的结果返回一个 Promise,这个 Promise 的结果将是上面显示的当前对象结果。

选项 2) 使用 promise 加载依赖项,然后在 promise 解决后执行逻辑。

下面是选项 2 的示例,使用延迟的 jQuery 样式。我通常更喜欢 when.jsQ。如果附加顺序很重要,这个例子可能会崩溃。

// Option 2
define([
    './abackendmodel'
], function(Model) {
    var dep1Promise = null;
    if (model.showDepedency) {
        var dep1Deferred = $.Deferred();
        dep1Promise = dep1Deferred.promise();

        require([
            './dependency'
        ], function(Dependency) {
            dep1Deferred.resolve(Dependency);
        }, dep1Deferred.reject); // Optionally reject the promise if there is an error finding the dependency.

    }
    return {
        show: function() {
            if (dep1Promise) {
                dep1Promise.then(function(Dep1) { 
                    var dep = new Dep1();
                    this.$el.append(dep);
                });
            }
        }
    };
});
于 2013-09-30T00:06:54.250 回答