Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

How to execute Ember.RSVP.all within an ember run loop correctly

I'm trying to execute a promise inside Ember.RSVP.all

App.Foo = Ember.Object.create({
    bar: function() {
        var configuration = ajaxPromise("/api/configuration/", "GET");
        Ember.RSVP.all([configuration]).then(function(response) {
            //do something with the response in here
        });
    }
});

But because my integration test mocks the xhr w/out a run loop the test fails with the expected error "You have turned on testing mode, which disabled the run-loop' autorun"

So I wrapped the RSVP with a simple ember.run like so

App.Foo = Ember.Object.create({
    bar: function() {
        var configuration = ajaxPromise("/api/configuration/", "GET");
        Ember.run(function() {
            Ember.RSVP.all([configuration]).then(function(response) {
                //do something with the response in here
            });
        });
    }
});

But I still get the error for some odd reason. Note -if I run later it's fine (this won't work though as I need to exec the async code for this test to work correctly)

App.Foo = Ember.Object.create({
    bar: function() {
        var configuration = ajaxPromise("/api/configuration/", "GET");
        Ember.run.later(function() {
            Ember.RSVP.all([configuration]).then(function(response) {
                //do something with the response in here
            });
        });
    }
});

Here is my ajaxPromise implementation -fyi

var ajaxPromise = function(url, type, hash) {
    return new Ember.RSVP.Promise(function(resolve, reject) {
        hash = hash || {};
        hash.url = url;
        hash.type = type;
        hash.dataType = 'json';

        hash.success = function(json) {
            Ember.run(null, resolve, json);
        };

        hash.error = function(json) {
            Ember.run(null, reject, json);
        };

        $.ajax(hash);
    });
}

How can I wrap the Ember.RVSP inside my ember run w/out it throwing this error?

Update

here is my test setup (including my helper)

document.write('<div id="ember-testing-container"><div id="wrap"></div></div>');
App.setupForTesting();
App.injectTestHelpers();

test("test this async stuff works", function() {
    visit("/").then(function() {
        equal(1, 1, "omg");
    });
});

The only part I've left out is that I'm using jquery-mockjax so no run loop wraps the xhr mock (and in part that's why I like this library, it fails a test when I don't wrap async code with a run loop as the core team suggests)

like image 586
Toran Billups Avatar asked Feb 14 '23 01:02

Toran Billups


2 Answers

This may have to do with how your tests are being run, so if you can provide the test, it will be helpful

I also noticed:

It turns out I believe you are also being (or will be soon) trolled by jQuery's jQXHR object being a malformed promise, the fulfills with itself for 0 reason, and enforcing its own nextTurn on you. Which is causing the autorun. This will only happen in the error scenario.

In ember data we sort this out, by stripping the then off the jQXHR object

see: https://github.com/emberjs/data/blob/4bca3d7e86043c7c5c4a854052a99dc2b4089be7/packages/ember-data/lib/adapters/rest_adapter.js#L539-L541

I suspect the following will clear this up.

var ajaxPromise = function(url, type, hash) {
    return new Ember.RSVP.Promise(function(resolve, reject) {
        hash = hash || {};
        hash.url = url;
        hash.type = type;
        hash.dataType = 'json';

        hash.success = function(json) {
            Ember.run(null, resolve, json);
        };

        hash.error = function(json) {
            if (json && json.then) { json.then = null } // this line

            Ember.run(null, reject, json);
        };

        $.ajax(hash);
    });
}

This is rather unfortunate, and various separate concepts and ideas are coming together to cause you pain. We hope to (very shortly) land Ember.ajax which normalizes all these crazy away.

Also feel free to checkout how ember-data is going this: https://github.com/emberjs/data/blob/4bca3d7e86043c7c5c4a854052a99dc2b4089be7/packages/ember-data/lib/adapters/rest_adapter.js#L570-L586

like image 169
Stefan Penner Avatar answered May 25 '23 09:05

Stefan Penner


I feel your pain on this Toran, I'm sure it's what Stefan's stated, we had to 1 off mockjax to get our tests to work with it.

https://github.com/kingpin2k/jquery-mockjax/commit/ccd8df8ed7f64672f35490752b95e527c09931b5

    // jQuery < 1.4 doesn't have onreadystate change for xhr
      if ($.isFunction(onReady)) {
        if (mockHandler.isTimeout) {
          this.status = -1;
        }
        Em.run(function () {
          onReady.call(self, mockHandler.isTimeout ? 'timeout' : undefined);
        });
      } else if (mockHandler.isTimeout) {
        // Fix for 1.3.2 timeout to keep success from firing.
        this.status = -1;
      }
like image 21
Kingpin2k Avatar answered May 25 '23 10:05

Kingpin2k