问题与Ember模型承诺

时间:2013-08-21 19:36:58

标签: ember.js ember-model

我试图用Ember Model做一些基本的东西,但我在承诺中经历了一些奇怪的行为。不确定我是否理解它应该如何运作。

所以,我有这条路线:

App.ProfilesIndexRoute = Ember.Route.extend {

  redirect: ->
    App.Profile.fetch().then (profiles) ->
      console.log profiles.get('length')
      @transitionTo 'profile', profiles.get('firstObject')

}

我只想让人们在访问/profiles/123时被重定向到/profiles(=第一个个人资料)。

以下是配置文件适配器:

App.Profile.adapter = Ember.Adapter.create {

  findAll: (klass, records) ->
    $.ajax('/api/users/' + $.cookie('user_id'), {
      type: 'get'
      headers: {
        'Content-Type': 'application/json'
        'Authentication-Token': $.cookie('token')
      }
      dataType: 'json'
    }).then (res) ->
      profiles = []
      // some stuff done here
      records.load klass, profiles

}

当我转到/profiles时,这是我在控制台中看到的内容:

0
Transitioned into 'profiles.index'
XHR finished loading: "http://localhost/api/users/456". 

0console.log profiles.get('length')的结果。似乎在AJAX调用有机会完成之前调用它。我在控制台中应该拥有的内容是这样的:

Transitioned into 'profiles.index'
XHR finished loading: "http://localhost/api/users/456". 
5

我在这里做错了什么?有人here建议我使用fetch代替find,但它似乎无法解决我的问题,因为事情没有以正确的顺序执行。

谢谢!

3 个答案:

答案 0 :(得分:1)

您应该重定向到afterModel挂钩的其他路线:

App.ProfilesIndexRoute = Ember.Route.extend {

  model: ->
    App.Profile.fetch()

  afterModel: (profiles, transition) =>
    @transitionTo 'profile', profiles.get('firstObject')

}

此外,由于您使用的是@,因此您应该使用粗箭=>来正确引用this

希望它有所帮助。

答案 1 :(得分:1)

我认为你覆盖适配器的方式是错误的:

您正在使用延迟的jquery ajax。但我认为你需要wrap that call in RSVP。因为ember使用RSVP来处理promisses。

查看该实现

App.Profile.adapter = Ember.Adapter.create({
    ajaxSettings: function(url, method) {
        return {
            headers: {
                'Content-Type': 'application/json'
                'Authentication-Token': $.cookie('token')
            },
            dataType: "json"
        };
    },
    findAll: function(klass, records) {
        var url = '/api/users/' + $.cookie('user_id'),
        self = this;

        return this.ajax(url).then(function(data) {
            self.didFindAll(klass, records, data);
            return records;
        });
    }   
});

我使用RESTAdapter中的findAll实现,只是更改了网址,以匹配您想要的内容。

但如果您的回复只返回一个对象,我认为find方法更好:

...
find: function(record, id) {
    var url = '/api/users/' + $.cookie('user_id'),
        self = this;

    return this.ajax(url).then(function(data) {
      self.didFind(record, id, data);
      return record;
    });
},
...

答案 2 :(得分:1)

由于this jsFiddle by Erik Bryn,我终于找到了解决问题的方法。

我在这里错过了return

App.Profile.adapter = Ember.Adapter.create {

  findAll: (klass, records) ->
    $.ajax('/api/users/' + $.cookie('user_id'), {
      type: 'get'
      headers: {
        'Content-Type': 'application/json'
        'Authentication-Token': $.cookie('token')
      }
      dataType: 'json'
    }).then (res) ->
      profiles = []
      // some stuff done here
      records.load klass, profiles
      return records // HERE

}

此外,我现在在init而不是ProfilesIndexRoute中使用redirect方法:

App.ProfilesIndexRoute = Ember.Route.extend {

  init: ->
    App.Profile.fetch().then (profiles) =>
      @transitionTo 'profile', profiles.get('firstObject')

}