Обещание AJAX без данных Ember
Я решил не использовать данные ember-data, так как он не готов и все еще меняется. Мое приложение только должно сделать несколько аякс-запросов в любом случае, чтобы не было слишком большой разницы. У меня возникли проблемы с пониманием того, как обращаться с ответом на ajax-обещание.
Когда мой пользователь загружает приложение, у них уже есть сеанс с проверкой подлинности. Я пытаюсь выполнить ping-сервер для этой информации о пользователях и отобразить его в моем шаблоне. Кажется, мой шаблон отображается до того, как мой запрос ajax возвращает результаты, а затем не обновляется с обещанием.
// 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>
Как я могу обновить шаблон, когда получаю ответ или задержку, пока у меня не будет ответа?
Ответы
Ответ 1
На самом деле ответ довольно прост: вам не нужно использовать обещание. Вместо этого просто верните пустой объект. Ваш код может выглядеть так:
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;
}
});
Что здесь происходит?
- Вы создаете пустой объект.
- Вы выполняете асинхронный вызов вашего API...
- ... и в вашем обратном вызове успеха вы заполняете пустой объект.
- Вы возвращаете свой пользовательский объект.
Примечание. Что происходит на самом деле? Поток, упомянутый выше, не является последовательностью, в которой эти действия происходят. На самом деле сначала выполняются точки 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;
}
});
Ответ 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.