Как обрабатывать модули AMD с условными требованиями?

Предположим, у меня есть модуль AMD, которому условно требуется второй модуль в некоторых средах:

define(["require"], function(require) {
  var myObj = { 
    foo: console.error.bind(console) 
  };
  if(browserEnv)
    require(["./conditional-polyfill"],function(polyfill){
      myObj.foo = console.log.bind(console,polyfill) ;
    });
  return myObj; //returns before conditional require is satisfied
});

Возникает вопрос: как я могу отложить возврат / обратный вызов метода define () ПОСЛЕ выполнения условного требования?

Т.е. приведенный ниже код не работает:

require(["module-from-above"],function(logger){
  logger.foo("Hello!"); //console.error gets called
});

Мои мысли по поводу решения этой проблемы:

  • Если я вставлю ./polyfill, все будет работать. Однако это просто обходит проблему и работает не во всех случаях. Я хочу сделать его модульным по какой-то причине.
  • Я мог бы вернуть объект Deferred вместо myObj, который будет выполнен ./conditional-polyfill позже. Это сработает, но действительно некрасиво звонить loggerDeferred.then(function(logger){ ... }); все время.
  • Я мог бы сделать плагин загрузчика AMD для этого модуля. И перезвоните, как только все будет готово. Опять же, это сработает, но плагины собственного загрузчика не работают с моим инструментом сборки.

Все решения, которые я могу придумать, - это скорее хаки, чем хороший код. Однако я думаю, что моя проблема не слишком надуманная. Итак, как с этим справиться?


person Maximilian Hils    schedule 15.01.2013    source источник


Ответы (2)


Вытолкнуть условие за пределы "фабричной функции" (имя, обычно используемое в сообществе AMD для обозначения функции обратного вызова require и define)

;(function() {

function factory(require, polyfill){
  var myObj = { 
    foo: console.error.bind(console) 
  }
  if(polyfill){
    myObj.foo = console.log.bind(console, polyfill)
  }
  return myObj
}

var need = ['require']

if(browserEnv){
  need.push("./conditional-polyfill")
}

define(need, factory)

})();
person ddotsenko    schedule 15.01.2013
comment
Это не касается моего случая (условное выражение зависит от другой зависимости), но я принимаю ваш ответ, поскольку вы предоставляете по крайней мере решение для некоторых случаев. - person Maximilian Hils; 11.07.2013

Как вы говорите, я бы использовал Deferred.

Отложенный шаблон - идеальное решение для такого рода проблем, потому что он позволяет согласованным образом связывать сложные асинхронные операции.

Это сделает ваш код немного больше, но это простое решение по сравнению с изменением загрузчика и инструментов сборки.

person DLeonardi    schedule 15.01.2013