如何正确执行ember运行循环中的Ember.RSVP.all

时间:2014-01-20 18:54:39

标签: ember.js rsvp.js

我试图在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
        });
    }
});

但是因为我的集成测试模拟了xhr w / out a run loop,测试失败并出现预期的错误"你已经打开测试模式,这会禁用运行循环'自动运行"

所以我用一个像这样的简单的ember.run包装RSVP

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

但我仍然因为一些奇怪的原因而得到错误。注意 - 如果我以后运行它很好(虽然因为我需要执行异步代码以使此测试正常工作,但这不会起作用)

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

这是我的ajaxPromise实现-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);
    });
}

我怎样才能将Ember.RVSP包裹在我的余烬中,并将其抛出此错误?

更新

这是我的测试设置(包括我的助手)

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

我唯一遗漏的部分是我使用jquery-mockjax所以没有运行循环包装xhr模拟(部分原因是我喜欢这个库的原因,它失败了测试当我没有用核心团队建议的运行循环包装异步代码时)

2 个答案:

答案 0 :(得分:7)

这可能与您的测试运行方式有关,因此如果您可以提供测试,那将会很有帮助

我也注意到了:

事实证明,我相信你也正在(或将很快)被jQuery的jQXHR对象所控制,这是一个错误的承诺,为了满足自己的原因,并强制执行自己的nextTurn。这导致自动运行。这只会发生在错误场景中。

在ember数据中,我们通过剥离jQXHR对象的then来对其进行排序

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

我怀疑以下内容会清除它。

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

这是相当不幸的,各种各样的概念和想法汇集在一起​​,给你带来痛苦。我们希望(很快)登陆Ember.ajax,将所有这些疯狂归正。

也可以随时查看ember-data的内容:https://github.com/emberjs/data/blob/4bca3d7e86043c7c5c4a854052a99dc2b4089be7/packages/ember-data/lib/adapters/rest_adapter.js#L570-L586

答案 1 :(得分:1)

我感觉到你对Toran的痛苦,我确信这是Stefan的说法,我们不得不关闭mockjax来让我们的测试与它一起工作。

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