【问题标题】:How to wait until find method has finished before doing further processing in Ember Model如何等到 find 方法完成后再在 Ember 模型中进行进一步处理
【发布时间】:2013-11-23 05:04:28
【问题描述】:

我如何才能等到我的 find 方法完成从后端加载模型?模型加载后,我想获取其他数据并用该数据装饰我的电影模型。对从中获取附加数据的外部 api 的请求基于电影模型的属性,例如年份和标题。

App.Movie.adapter = Ember.Adapter.create({
  find: function(record, objectId) {
    return Ember.$.ajax({
      headers: {
        'X-Parse-Application-Id': '',
        'X-Parse-REST-API-Key': ''
      },
      type: 'GET',
      url: 'https://api.parse.com/1/classes/Movie' + '/' + objectId
    }).then(function(data) {
      record.load(objectId, data);
    });
  }
});

App.MoviesMovieRoute = Ember.Route.extend({
  model: function (movie) {
    return App.Movie.find(movie.movie_id);
  },

  afterModel: function(movie, transition) {
    // currently undefined, undefined
    console.log(movie.get('title'), movie.get('year'));
  }
});

App.MoviesMovieController = Ember.ObjectController.extend({
  contentObserver: function () {
    // fetch additional data from external api
  }.observes('content')
});

谢谢

【问题讨论】:

  • 尝试在方法结束时输入打印语句。这将表明该方法已经完成
  • 如何将您的 ajax 调用作为 Async: false 运行?在继续之前,它必须得到答案。

标签: javascript ember.js ember-model


【解决方案1】:

对于 ember 模型,使用 fetch,它会返回 Promise,而 ember 会等到解析该模型后再执行下一个模型。

return App.Movie.fetch(movie.movie_id);

find 建立一个虚拟记录并立即返回记录(并在数据可用时填充它),而 fetch 建立记录和一个承诺,并返回承诺,当记录被填充时解析为记录.

它们都将使用适配器的 find 方法。

App.MoviesMovieRoute = Ember.Route.extend({
  model: function (movie) {
    return App.Movie.find(movie.movie_id);
  },

  afterModel: function(movie, transition) {
    // currently undefined, undefined
    console.log(movie.get('title'), movie.get('year'));
  },

  serialize: function(model){
    return { movie_id: model.get('whateverfieldhastheid')};
  }
});

【讨论】:

  • 是否可以从动态url部分获取id?那么页面/浏览器重新加载后单个视图是否正确呈现?我是否必须将 return 语句放在 ajax 请求之前以返回一个 Promise,或者是否可以省略该 return 语句?谢谢
  • id 和 url 部分似乎没问题。但我在控制台中收到此错误消息:“断言失败:无法在未定义的对象上使用 'id' 调用 get。”有什么想法吗?
  • 你需要在你的路由中实现序列化钩子。我给你找个例子。
  • 对不起... ;-) 但是现在只有一个白屏。控制台中没有任何内容被渲染并且没有错误消息。可能的原因可能是单个视图是列表视图的子路由?谢谢
  • 之前渲染过?
【解决方案2】:

一种方法是使用 RSVP Promise 实现 find(),如下所示:

App.Movie = Ember.Object.extend({

});

App.Movie.reopenClass({
    find: function(objectId) {
        return Ember.RSVP.Promise(function(resolve, reject) {
            Ember.$.ajax({
                type: 'GET',
                url: 'https://api.parse.com/1/classes/Movie' + '/' + objectId
            }).success(function(data) {
                resolve(data);
            }).fail(function(data) {
                reject(data);
            })
        }
    }
});

然后,在您的路线中,您可以将 then 添加到您的承诺中:

App.MoviesMovieRoute = Ember.Route.extend({
    model: function (movie) {
        var movie = App.Movie.find(movie.movie_id); 
        movie.then(function() {
            // Gets called once the server returned loaded
            console.log(movie.get('title'), movie.get('year'));
        }, function() {
            // FailureHandler
        });
        return movie;
    },
});
  • 请注意,这根本没有使用 EmberData。不知道这是不是要求?

【讨论】:

    猜你喜欢
    • 2017-02-21
    • 1970-01-01
    • 2015-08-13
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多