3

I'm attempting to build a non blocking async call in an Ember.js app without using Ember Data.

I have the following Ember.js model:

App.Player = Ember.Object.extend({
    id: '',
    alias: '',
    name: '',
    twitterUserName: '',
    isFeatured: ''
});

App.Player.reopenClass({
    getPlayers: function () {
        var players = Ember.ArrayProxy.create({ content: [] });
        $.getJSON("/api/players").then(function (response) {
            response.forEach(function (p) {
                players.pushObject(App.Player.create(p));
            });
        });
        return players;
    }
});

And I am calling it as follows in my route:

App.IndexRoute = Ember.Route.extend({
    model: function (params) {
        return App.Player.getPlayers();
    }
});

For some reason I am getting the following javascript error:

Uncaught TypeError: Object # has no method 'forEach'

I've tried a few variants I have seen around but nothing seems to work. Any help would be appreciated...

EDIT - Found the solution with some help from Darshan, here's the working code:

App.Player.reopenClass({
    getPlayers: function () {
        var players = [];
        $.ajax({
            url: "/api/players",
        }).then(function (response) {
            response.players.forEach(function (player) {
                var model = App.Player.create(player);
                players.addObject(model);
            });
        });
        return players;
    }
});

Your response.forEach suggests that you are expecting the json response body to be an array. It is probably wrapped in some root element like players or data like so.

{
  "players": [...]
}

If that is the case you need to use forEach on that root element like response.players.forEach.

You also want to restructure that code to return a promise directly. The Ember router will then pause until your json is loaded and only proceed after it finishes. Something like this,

getPlayers: function () {
  return $.getJSON("/api/players").then(function (response) {
    var players = Ember.ArrayProxy.create({ content: [] });
    response.players.forEach(function (p) {
      players.pushObject(App.Player.create(p));
    });

    return players;
  });
}

Returning players resolve the promise. And Ember understands that when a promise resolves that result is the model.

4

1 回答 1

4

response.forEach建议您期望 json 响应正文是一个数组。它可能被包裹在一些类似playersdata类似的根元素中。

{
  "players": [...]
}

如果是这种情况,您需要forEach在该根元素上使用response.players.forEach.

您还想重组该代码以直接返回一个承诺。Ember 路由器将暂停,直到您的 json 被加载,并且仅在完成后继续。像这样的东西,

getPlayers: function () {
  return $.getJSON("/api/players").then(function (response) {
    var players = Ember.ArrayProxy.create({ content: [] });
    response.players.forEach(function (p) {
      players.pushObject(App.Player.create(p));
    });

    return players;
  });
}

返回players解决承诺。并且 Ember 明白,当一个 Promise 解决时,结果就是model.

于 2013-07-18T03:37:48.230 回答