2013-03-25 5 views
16

私はember-dataを生産準備中でなく変更していないため、使用しないことに決めました。私のアプリは、とにかくいくつかのAjaxリクエストを作成する必要がありますので、それほど大きな違いはありません。私は、ajaxの約束の対応をどのように扱うかを理解するのに問題があります。Emberデータのない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> 

どのように応答を持ってまで、私が応答または遅延レンダリングを受信したとき、私はテンプレートを更新しますか?

答えて

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

+0

promise/jQuery.Deferredを使用できます。 – mavilein

+0

@mavilein、配列にjQuery約束を使用した例がありますか?私はオブジェクトに対してjQueryの約束を使うことができることを発見しましたが、配列に対して約束を使用しようとすると型エラーが発生します。 –

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

エンバーはenoughtスマートであり、あなたが返す約束、それは解決しています一度モデルが正しく設定されますを処理する方法を知っている、あなたjQueryの約束を返すこともできますが、それはあなたに奇妙な振る舞いを与えます。

+0

ちょうど簡単なテストを行い、Ember Deferredを使用するとEmberのローディングサブステージも利用できます。 Emberの配列ロードを使用している場合、substatesは動作していないようです(http://jsfiddle.net/UJ4Su/10/) – Sarus

+3

Ember.Deferredは[RSVP.promise]を支持しているようですが、 (http://emberjs.com/guides/deprecations/#toc_deprecate-ember-deferredmixin-and-ember-deferred)。 –

0

あなたが同様にそうようなあなたのApplicationRouteためのモデルとして、現在のユーザーを設定することができます。約束は果たすまたは拒否のいずれかまで

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

getCurrentUser()ので、リターンの約束を、移行は中断されます。

これは、時間の移行が完了するとモデルが初期化され、テンプレートでレンダリングされたことがわかるので便利です。

あなたはEmberガイドでread up more about async routingできます。

関連する問題