Welcome to OGeek Q&A Community for programmer and developer-Open, Learning and Share
Welcome To Ask or Share your Answers For Others

Categories

0 votes
469 views
in Technique[技术] by (71.8m points)

asynchronous - AJAX promise without Ember Data

I have decided to not use ember-data as it's not production ready and still changing. My app only needs to make a few ajax requests anyway so it shouldn't make too big of a difference. I am having trouble understanding how to handle an ajax promise response.

When my user loads the app they already have an authenticated session. I am trying to ping the server for that users info and display it in my template. It seems my template is rendered before my ajax request returns results and then does not update with the 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;
        });
    }
});

In my template:

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

How would I update the template when I receive a response or delay rendering until I have a response?

See Question&Answers more detail:os

与恶龙缠斗过久,自身亦成为恶龙;凝视深渊过久,深渊将回以凝视…
Welcome To Ask or Share your Answers For Others

1 Reply

0 votes
by (71.8m points)

Actually the answer is quite easy: You do not need to use a promise. Instead just return an empty object. Your code could look like this:

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

What is happening here?

  1. You create an empty object.
  2. You make an asynchronous call to your API...
  3. ... and in your success callback you fill your empty object.
  4. You return your user object.

Note: What is really happening? The flow mentioned above is not the sequence in which those actions are happening. In reality the points 1,2 and 4 are performed first. Then some time later, when the response returns from your server, 3 is executed. So the real flow of actions is: 1 -> 2 -> 4 -> 3.

So the general rule is to always return an object that enables Ember to do its logic. No values will be displayed first in your case and once your object is filled Ember will start do its magic and auto update your templates. No hard work needs to be done on your side!


Going beyond the initial question: How would one do this with an array? Following this general rule, you would return an empty array. Here a little example, which assumes, that you might like to get all users from your backend:

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

与恶龙缠斗过久,自身亦成为恶龙;凝视深渊过久,深渊将回以凝视…
OGeek|极客中国-欢迎来到极客的世界,一个免费开放的程序员编程交流平台!开放,进步,分享!让技术改变生活,让极客改变未来! Welcome to OGeek Q&A Community for programmer and developer-Open, Learning and Share
Click Here to Ask a Question

...