Overriding DefaultResolver Methods

Can you return a promise to the resolved object? It would be nice to use RequireJS during development so you don’t have to constantly recompile the entire app.

Can you elaborate a bit more about what you’re trying to accomplish?

Sure. I’d like to use RequireJS on the client side when developing Ember applications, and I’d like the resolver to pull dependencies using it. For example, view:index would resolve to the eventual result of require('app/views/index'). In order for this to work, the resolver needs to work asynchronously. I know this won’t work optimizing, as static analysis won’t see that, but it will be simple to just tell r.js to include all modules in my app/ dir so the production build works.

Are you familiar with the work that’s being done with Ember App Kit and ECMAScript 6 modules?

EAK has a resolver that does what you describe https://github.com/stefanpenner/ember-app-kit/blob/master/vendor/loader.js If you want to roll your own, you could use their code as reference.

Yup, I’m familiar with it. It doesn’t do what I’m describing.

The question I should have asked was this: Are there plans to support resolving dependencies asynchronously? Without this, I don’t see how you could use an AMD loader on the client side with Ember.

Here is a contrived example that doesn’t work:

Ember.Application.create({
  Resolver: Ember.DefaultResolver.extend({
    resolveTemplate: function(parsedName) {
      return new Ember.RSVP.Promise(function(resolve, reject) {
        return resolve(Ember.Handlebars.compile("Hi, I was resolved asynchronously."));
      });
    }
  })
});

I don’t know the answer to this question, but I tweeted it and let’s see if someone responds :smile:

I just tweeted at @wycats :slight_smile:

Making the resolver work asynchronously would mean that every time Ember wanted an object, it would need to get it asynchronously.

We looked at this at one point, and it’s a very invasive change that also has bad performance implications. The way people use AMD today is to expect the necessary modules to be loaded by the time the resolver is invoked.

You can use router hooks (beforeModel, for example), to asynchronously fetch code and load it before entering some part of your app, but by the time Ember needs the object, it will be available synchronously.

I don’t really think it makes sense in production for every module to be fetched synchronously to begin with.

1 Like

I assume you meant to say that it doesn’t make sense in production for every module to be fetched asynchronously? I agree with you here.

There is a huge benefit to doing this in development with AMD, though. Not needing to recompile your entire application for every code change is a huge win. Loader plugins with RequireJS also make transpilation on-the-fly of a zillion different things totally transparent. I could go on and on.

After an app is optimized for production, all of the modules are available synchronously.

What about an optional flag that indicates the Resolver should expect a promise as a result?

The issue is less about the public programming model and more about the fact that literally every part of the system that interacted with the container would have to become promise-y. If you wanted to instantiate an object that had injections, that object instantiation would become a promise.

Every container.lookup becomes a promise!

My initial inclination when we started with the container was to make it async by default but after a few hours of discussion with @krisselden it became obvious that it had very far-reaching ramifications.

It sucks that the state of JavaScript build tools makes this a relevant issue. Literally no other build system requires compilation of source files that haven’t changed. See this gist for a proposal I wrote recently for allowing on-the-fly compilation of just source files that have changed across an arbitrarily complex pipeline.

So, as I read through this Thread, am I right that the answer to my question about asynchronous template loading (see: Asynchronous Template Loading) is simply it’s not possible, @wycats ?

I think actual design of defaultResolver is not good. I love Ember but as tkellen said. We need async loading of content. We can use another solution based on simple callback. Default behavior will call this function immediately (without speed impact) and asynchronous function when will get content.

Ember.Application.create({
   Resolver: Ember.DefaultResolver.extend({
       resolveTemplate: function(parsedName, callback) {