【问题标题】:What's the proper way to do async calls in Ember?在 Ember 中进行异步调用的正确方法是什么?
【发布时间】:2015-06-12 00:19:54
【问题描述】:

对于特定的服务调用,我使用的是 jQuery 而不是 ember 数据:

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

这会破坏 ember 的测试:

未捕获的错误:断言失败:您已打开测试模式,这禁用了运行循环的自动运行。 您需要在运行中包装任何具有异步副作用的代码

我可以通过在我的 promise 的 .then 函数中添加一个 run 来解决这个问题:

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

但这对我不起作用,因为 Ember.run(..) 不返回任何内容,所以我的承诺解析为未定义。我已经看到了一些将 Ember.run 移出一级的建议,以便它包装返回承诺的方法。这将返回正确的值,但测试将继续失败。

在不破坏测试的情况下,返回解析为值的 Promise 的正确方法是什么?

谢谢!

编辑 1

我确实可以使用此代码:

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

这是正确的做法吗?感觉就像做一个 ajax 调用增加了很多复杂性。

【问题讨论】:

    标签: ember.js promise ember-cli


    【解决方案1】:

    将您的异步调用封装在 Ember.RSVP.Promise 然后 resolve。示例(取自 routemodel 钩子):

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

    【讨论】:

    • 请不要,在 $.get` 上使用 Ember.RSVP.resolve 而不是创建明确的新承诺。
    • 这对我不起作用。 store.pushPayload 不返回值,因此该快捷方式不起作用。而且它仍然会绊倒测试。我确实让它工作了(见编辑),但根据@Benjamin Gruenbaum 的评论,我不确定它是否正确。
    【解决方案2】:

    编辑:

    看起来在 Ember 1.13+ 中,执行 Ajax 的首选方式是使用 Ember Ajax - https://github.com/ember-cli/ember-ajax


    由于您只是使用 jQuery 的 $.ajax 方法,您应该使用实际上包含在使用 ember-cli 创建的所有新 Ember 项目中的“ic-ajax”库。

    这个库基本上将所有 JQuery Ajax 调用封装在 Ember.run 中,因此您可以轻松测试。

    例如,使用您的示例:

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

    会变成

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

    比必须自己将所有 ajax 调用包装在 Ember.run 中要干净得多

    【讨论】:

    • 现在看来 ember-ajax 建议不要使用 ic-ajax。
    • 是的,在帖子顶部添加了一个编辑,其中包含指向 ember-ajax 存储库的链接
    【解决方案3】:

    现在有一个更新/更高级的东西可以使用:Ember Fetch

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 1970-01-01
      • 2017-03-07
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2015-05-31
      • 1970-01-01
      相关资源
      最近更新 更多