2013-03-25 64 views
16

我決定不使用餘燼數據,因爲它沒有生產準備好,仍在變化。我的應用程序只需要提出一些ajax請求,所以它不應該有太大的區別。我無法理解如何處理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> 

如何當我收到的響應或延遲渲染,直到我有一個迴應,我會更新模板?

回答

37

其實答案很簡單:你不需要使用承諾。而只是返回一個空的對象。您的代碼可能如下所示:

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將開始做它的魔法並自動更新你的模板。沒有艱辛的工作需要在你身邊完成!


超越最初的問題:一是如何將一個數組做到這一點? 遵循這條一般規則,您將返回一個空數組。這裏一個小例子,它假定,你可能想從你的後臺獲取所有用戶:

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

有沒有什麼辦法可以找出#3完成的時候?即當#3完成時調用控制器方法。 .observes()似乎沒有幫助。 – Rushi 2013-03-31 17:16:01

+0

你可以使用promise/jQuery.Deferred。 – mavilein 2013-04-01 20:10:23

+0

@mavilein,你有沒有使用數組的jQuery承諾的例子?我發現我可以爲一個對象使用jQuery承諾,但是當我嘗試爲數組使用承諾時出現類型錯誤。 – 2013-05-29 14:02:59

6

我會使用,而不是如前面提到返回一個空數組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(); 
} 

灰燼是聰明的足夠多,並且知道如何處理返回的承諾,一旦它的解決模式將設置正確,你也可以返回一個jQuery的承諾,但它會給你一些奇怪的行爲。

+0

剛做了一個快速測試,使用Ember Deferred可以讓您充分利用Ember的加載子狀態。如果你只是使用一個Ember數組加載子狀態似乎不起作用(http://jsfiddle.net/UJ4Su/10/) – Sarus 2014-02-25 02:59:02

+3

只是一個說明,Ember.Deferred似乎[現在不贊成使用RSVP.promise] (http://emberjs.com/guides/deprecations/#toc_deprecate-ember-deferredmixin-and-ember-deferred)。 – 2014-11-21 05:11:50

0

可以和設置當前用戶作爲模型爲您ApplicationRoute像這樣:

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

由於getCurrentUser()回報承諾,過渡將暫停,直至承諾履行兩種或拒絕。

這很方便,因爲在轉換完成之後,您的模型將被初始化,您將看到它在模板中呈現。

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