Question

Let's assume I have an AMD module that conditionally requires a second module in some environments:

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

The question is: How can I delay the define() call to return/callback AFTER the conditional require has been completed?

I.e. the code below fails:

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

My thoughts on solutions to this issue:

  • If I inline ./polyfill, everything would work. However, that just circumvents the problem and doesn't work for every case. I want it modularized for a reason.
  • I could return a Deferred object instead of myObj that gets fulfilled by ./conditional-polyfill later. This would work, but it's really ugly to call loggerDeferred.then(function(logger){ ... }); all the time.
  • I could make a AMD loader plugin for this module. And call the callback as soon as everything is ready. Again, this would work, but own loader plugins don't work with my build tool.

All solutions I can think of are more hacks than good code. However, I think that my issue isn't too far-fetched. So, how to handle this?

Était-ce utile?

La solution

Push conditional outside of "factory function" (the name commonly used in AMD community to refer to the require's and define's callback function)

;(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)

})();

Autres conseils

I would use a Deferred, as you say.

The deferred pattern is the ideal solution to this kind of issue, because it allows you to tie complex async operations together in a consistent way.

It will make your code a bit larger, but its a simple solution compared to modifying the loader and the build tools.

Licencié sous: CC-BY-SA avec attribution
Non affilié à StackOverflow
scroll top