Ember.js 如何在Ember运行循环中正确执行Ember.RSVP.all

Ember.js 如何在Ember运行循环中正确执行Ember.RSVP.all,ember.js,rsvp.js,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 t

我试图在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,因此测试失败,出现预期错误“您已打开测试模式,该模式禁用了运行循环“自动运行”

所以我用一个简单的余烬包住了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
            });
        });
    }
});
但我还是因为一些奇怪的原因得到了这个错误。注意-如果我稍后运行,这没问题(但这不起作用,因为我需要执行异步代码才能使此测试正常工作)

以下是我的ajaxPromise实施-仅供参考

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包装在我的Ember运行中,并抛出此错误

更新

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

document.write(“”);
App.setupForTesting();
App.injectTestHelpers();
test(“testthismasync-stuff-works”,function()){
访问(“/”)。然后(函数(){
相等(1,1,“omg”);
});
});

我唯一遗漏的部分是我使用的是jquery mockjax,因此没有运行循环包装xhr mock(这就是为什么我喜欢这个库的部分原因,当我没有像核心团队建议的那样用运行循环包装异步代码时,它会使测试失败)

这可能与测试的运行方式有关,因此如果您能够提供测试,它将非常有用

我还注意到:

事实证明,我相信您也被jQuery的jQXHR对象(或者很快就会被)所迷惑,因为它是一个格式不正确的承诺,它以0为理由实现了它自己,并在您身上强制执行它自己的nextTurn。这导致了自动运行。这只会发生在错误场景中

在余烬数据中,我们通过剥离jQXHR对象的
然后
来对其进行排序

见:

我想下面会澄清这一点

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的运行情况:

我感觉到您在这台Toran上的痛苦,我相信这是Stefan所说的,我们必须关闭mockjax才能让测试使用它

//jQuery<1.4没有对xhr进行onreadystate更改
如果($.isFunction(onReady)){
if(mockHandler.isTimeout){
这个状态=-1;
}
Em.run(函数(){
onReady.call(self,mockHandler.isTimeout?'timeout':未定义);
});
}else if(mockHandler.isTimeout){
//修正了1.3.2超时以防止成功触发。
这个状态=-1;
}

我已经更新了上面的内容-让我给你一个快速运行的建议。你不会错过我上面提到的额外好处吗(我希望在运行循环的情况下执行异步操作时测试失败)?是的,你不会这么做的。无论如何,Ember.ajax会很好地结束这个过程,人们的痛苦应该会消失。Toran,它在运行循环中包装响应的代码路径,本质上与在运行循环中包装响应/拒绝方法相同。斯特凡,是的,我们知道这是一个创可贴修复,而我们已经把我们所有的测试从茉莉花迁移到QUnIT和建立集成测试。我们实际上懒惰地等待瑞安佛罗伦萨的特性在我们改变之前被拉/拒绝。现在我看了看,我看到他刚刚启动了球。
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");
    });
});
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);
    });
}
    // 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;
      }