2013-09-29 3 views
2

Я работаю с чем-то, что кажется идеальным для DI, но оно добавляется к существующей структуре, которая не имела этого в виду, когда она была написана. Конфигурация, определяющая зависимости, поступает из базовой модели. На самом деле это не полная конфигурация, в данный момент в ней в основном содержится ключ, который может использоваться для определения определенного вида, должен быть доступен или нет.Требование переназначения RequireJS для настраиваемой инъекции зависимостей

Я использую требуют поэтому зависимость выглядит примерно так

// 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); 
      } 
     } 
    }; 
}); 

Это далеко простираются от фактического кода но Важной частью является то, как требуют работы. Обратите внимание, что в коде инжектора требуется зависимость и используется в методе 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); 
      } 
     } 
    }; 
}); 

Очевидно, что это имеет проблемы. Если show вызывается до того, как асинхронный вызов будет завершен, то Dep1 по-прежнему будет иметь значение null. Таким образом, мы действительно не показываем зависимость, которая является целью, и, очевидно, в этом случае будут возникать ошибки JS. Кроме того, мы по-прежнему используем if чек на шоу, который мне не нравится, но прецедент заключается в том, что зависимость может быть или не быть, и мы просто не хотим ее требовать, если она не нужна, поэтому я не могу быть способный обойти это. Также имейте в виду, что model.showDependency на самом деле не является логическим значением. Он может иметь несколько значений, которые требовали бы для разных зависимостей. Я просто убираю его здесь для простоты понимания основной проблемы.

Идея два Это менее затвердевает то я не думаю, что это будет даже работать, но я рассмотрел играть с требуют config.path материала. Моя идея состояла в основном с двумя конфигурациями, так что './dependency' указывал на разные места. Проблема с этим, несмотря на то, что значение model.showDependency является конфигурацией, является тем же самым требованием конфигурации, поэтому не может изменить это во время выполнения. Может быть, есть какая-то магия, которая может быть сделана здесь, как отдельный путь к каталогу просмотра, и использование объекта фабричного типа, чтобы вернуть тот, который нам интересен, но так как это в конечном итоге приведет к такому же поведению async в Идея одна Я не думаю, что покупает мне что-нибудь (это в основном то же самое).

Идея три Есть возвратную зависимость нулевой базы по атрибуту model.showDependency. Это может быть лучшее решение прямо сейчас. Я все еще придерживаюсь if, но я не думаю, что это уходит. Также это предотвращает вызов вызывающего кода инициализации.

Любые лучшие идеи?

ответ

1

Почему бы не попробовать использовать обещание для загрузки зависимости?

У вас есть два варианта, в зависимости от того, как ваш код должен работать.

Вариант 1) Возвратите обещание для результата «вид/инжектор модуля», результатом этого обещания будет то, что было показано выше.

Вариант 2) Используйте обещание загрузить зависимость, а затем выполните логику, как только обещание будет разрешено.

Ниже приведен пример варианта 2, используя стиль JQuery отложенный. Я обычно предпочитаю when.js или Q. Этот пример может развалиться, если порядок добавления является важным.

// 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); 
       }); 
      } 
     } 
    }; 
}); 
+0

Я рассмотрел использование обещаний с помощью моего решения «Идея один». На самом деле я тестировал его, и он работает, но я действительно надеялся на что-то более чистое. В реальном приложении 'model.showDependency' не является bool, поэтому это может привести к взрыву кода. Конечно, я мог бы инкапсулировать логику загрузки зависимостей в собственный модуль. Это, вероятно, будет лучшим решением, но я надеюсь на что-то лучшее. Я выберу этот ответ, если не получу ничего лучше. – ralphinator80

Смежные вопросы