1
votes

For a specific service call, I'm using jQuery instead of ember data:

return Ember.$.get(url).then((json) => {
  this.store.pushPayload('user', json);
  return this.store.getById('user', json.user.id);
});

This breaks ember's testing:

Uncaught Error: Assertion Failed: You have turned on testing mode, which disabled the run-loop's autorun. You will need to wrap any code with asynchronous side-effects in a run

I can fix this by adding a run inside my promise's .then function:

return Ember.$.get(url).then((json) => {
  Ember.run(() => {
    this.store.pushPayload('user', json);
    return this.store.getById('user', json.user.id);
  })
});

This doesn't work for me though, because Ember.run(..) doesn't return anything, so my promise resolves to undefined. I've seen some suggestions to move Ember.run out one level so it wraps the method returning the promise instead. This will then return the correct value, but the tests will continue to fail.

What's the proper way to return a promise that resolves to a value, while not breaking tests?

Thanks!

Edit 1

I did get it working with this code:

var self = this;
return Ember.$.get(url).then((json) => {
    return new Ember.RSVP.Promise(function(resolve, reject) {
      Ember.run(function() {
        self.store.pushPayload('user', json);
        var user = self.store.getById('user', json.user.id);
        debugger;
        resolve(user);
      });
    });
});

Is this the right way to do it? It feels like a lot of added complexity just to do an ajax call.

3

3 Answers

0
votes

Wrap your async call in an Ember.RSVP.Promise then resolve. Example (taken from a route's model hook):

var self = this;
return new Ember.RSVP.Promise(function(resolve, reject) {
    Ember.$.get(url).then((json) => {
        var record = self.store.pushPayload('user', json);
        Ember.run(null, resolve, record);
        return record;
    });
});
0
votes

EDIT:

Looks like in Ember 1.13+, the prefered way of doing Ajax is using Ember Ajax - https://github.com/ember-cli/ember-ajax


Since you are just using jQuery's $.ajax methods, you should be using the "ic-ajax" lib that is actually included in all new Ember projects created with ember-cli.

This library basically does all the wrapping of the JQuery Ajax calls in an Ember.run so you can easily test.

For example, using your example:

import Ember from 'ember'
....
....
return Ember.$.get(url).then((json) => {
  this.store.pushPayload('user', json);
 return this.store.getById('user', json.user.id);
});

would become

import Ember from 'ember'
import request from 'ic-ajax'
....
....
return request(url).then((json) => {
    ....
});

Much cleaner than having to wrap all your ajax calls in Ember.run yourself

0
votes

And now there's an even newer/fancier thing to use: Ember Fetch.