【问题标题】:AJAX promise without Ember Data没有 Ember 数据的 AJAX 承诺
【发布时间】:2013-03-25 05:45:37
【问题描述】:

我决定不使用 ember-data,因为它还没有准备好生产并且仍在变化。无论如何,我的应用程序只需要发出一些 ajax 请求,所以它不应该有太大的不同。我无法理解如何处理 ajax 承诺响应。

当我的用户加载应用程序时,他们已经拥有经过身份验证的会话。我正在尝试 ping 服务器以获取该用户信息并将其显示在我的模板中。似乎我的模板是在我的 ajax 请求返回结果之前呈现的,然后没有使用 promise 进行更新。

// route
App.ApplicationRoute = Ember.Route.extend({
    setupController: function(){
        this.set("currentUser", App.User.getCurrentUser());
    }
});


// model
App.User = Ember.Object.extend({
    email_address: '',
    name_first: '',
    name_last: '',
    name_full: function() {
        return this.get('name_first') + ' ' + this.get('name_last');
    }.property('name_first', 'name_last')
});
App.User.reopenClass({
    getCurrentUser: function() {
        return $.ajax({
            url: "/api/get_current_user",
            type: "POST",
            data: JSON.stringify({})
        }).then(function(response) {
            return response;
        });
    }
});

在我的模板中:

<h1> Hey, {{App.currentUser.name_first}}</h1>

当我收到响应或延迟渲染直到收到响应时,我将如何更新模板?

【问题讨论】:

    标签: asynchronous ember.js


    【解决方案1】:

    其实答案很简单:你不需要使用 Promise。而是只返回一个空对象。您的代码可能如下所示:

    App.User.reopenClass({
        getCurrentUser: function() {
            var user = App.User.create({}); //create an empty object
            $.ajax({
                url: "/api/get_current_user",
                type: "POST",
                data: JSON.stringify({})
            }).then(function(response) {
                user.setProperties(response); //fill the object with your JSON response
            });
            return user;
        }
    });
    

    这里发生了什么?

    1. 您创建了一个空对象
    2. 您对 API 进行异步调用...
    3. ... 在您的成功回调中填充您的空对象。
    4. 您返回您的用户对象。

    注意:真正发生了什么? 上面提到的流程并不是这些动作发生的顺序。实际上,首先执行第 1,2 和第 4 点。然后一段时间后,当响应从您的服务器返回时,执行 3。 所以真正的动作流程是:1 -> 2 -> 4 -> 3。

    所以一般规则是始终返回一个使 Ember 能够执行其逻辑的对象。 在您的情况下,不会首先显示任何值,一旦您的对象被填充,Ember 将开始发挥它的魔力并自动更新您的模板。无需为您做任何艰苦的工作!


    超越最初的问题:如何使用数组做到这一点? 按照这个一般规则,您将返回一个空数组。下面是一个小示例,假设您可能希望从后端获取所有用户:

    App.User.reopenClass({
        getAllUsers: function() {
            var users = []; //create an empty array
            $.ajax({
                url: "/api/get_users",
            }).then(function(response) {
                response.forEach(function(user){
                    var model = App.User.create(user); 
                    users.addObject(model); //fill your array step by step
                });
            });
            return users;
        }
    });
    

    【讨论】:

    • 有什么办法可以知道#3 何时完成?即当 #3 完成时调用控制器方法。 .observes() 似乎没有帮助。
    • 你可以使用 promise/jQuery.Deferred。
    • @mavilein,你有使用 jQuery Promise 作为数组的例子吗?我发现我可以对对象使用 jQuery Promise,但是当我尝试对数组使用 Promise 时出现类型错误。
    • 我想我没有正确理解你的问题。想发布一个小代码sn-p吗?
    • 我很想有一个示例代码在 #3 完成时调用控制器(jquery.defered)。在后端成功删除或添加对象操作后,我需要该代码来更新表
    【解决方案2】:

    我会使用 Ember.Deferred 而不是如前所述返回一个空数组。

    App.User.reopenClass({
      getAllUsers: function() {
        var dfd = Ember.Deferred.create();
        var users = [];
    
        $.ajax({
            url: "/api/get_users",
        }).then(function(response) {
            response.forEach(function(user){
                var model = App.User.create(user); 
                users.addObject(model);
            });
            dfd.resolve(users);
        });
        return dfd;
      }
    });
    

    在你的模型钩子中你所要做的就是这个

    model: function(){
      return App.User.getAllUsers();
    }
    

    Ember 足够聪明,知道如何处理您返回的承诺,一旦解决,模型将被正确设置,您也可以返回 jQuery 承诺,但它会给您一些奇怪的行为。

    【讨论】:

    【解决方案3】:

    您也可以将当前用户设置为您的 ApplicationRoute 的模型,如下所示:

    App.ApplicationRoute = Ember.Route.extend({
        model: function() {
            return App.User.getCurrentUser();
        }
    });
    

    由于getCurrentUser() 返回一个承诺,转换将暂停,直到承诺履行或拒绝。

    这很方便,因为在转换完成时,您的模型已初始化,您将看到它在模板中呈现。

    您可以在 Ember 指南中read up more about async routing

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2018-12-06
      • 2014-08-16
      • 1970-01-01
      • 2020-02-10
      • 1970-01-01
      • 1970-01-01
      相关资源
      最近更新 更多