4

app.js ファイルをビルドするコーヒー トースター (ステッチ用の素晴らしい NPM モジュール) で coffeescript を使用してアプリを作成しています。

私のアプリケーション クラスとテンプレートの多くは現在のユーザーに関する情報を必要とするため、クラス User (Backbone.Model を拡張) のインスタンスをメインの Application クラス (Backbone.Router を拡張) のプロパティとして格納しています。

初期化ルーチンの一部として、サーバーからユーザーを取得します (認証、役割、アカウントの切り替えなどを処理します)。そのコーヒースクリプトは次のとおりです。

@user = new models.User
@user.fetch()
console.log(@user) 
console.log(@user.get('email'))   

最初のログ ステートメントは、正しい Backbone.Model 属性オブジェクトをコンソールに出力します。

User
_changing: false
_escapedAttributes: Object
_pending: Object
_previousAttributes: Object
_silent: Object
attributes: Object
  account: Object 
  created_on: "1983-12-13 00:00:00"
  email: "ben@accomplicecreative.com"
  icon: "0"
  id: "1"
  last_login: "2012-06-07 02:31:38"
  name: "Ben Ipsen"
  roles: Object
__proto__: Object
changed: Object
cid: "c0"
id: "1"
__proto__: ctor
app.js:228

ただし、ログに記録されたときにモデル属性がコンソールに明確に存在するにもかかわらず、2番目は未定義を返します。

さらに面白いことに、コンソールに「window.app.user.get('email')」と入力すると、手動で「ben@accomplicecreative.com」の期待値が返されます...?

参考までに、initialize メソッドを app.js ファイルにコンパイルする方法を次に示します。

Application.prototype.initialize = function() {
  var isMobile;
  isMobile = navigator.userAgent.match(/(iPhone|iPod|iPad|Android|BlackBerry)/);
  this.helpers = new views.DOMHelpers().initialize().setup_viewport(isMobile);
  this.user = new models.User();
  this.user.fetch();
  console.log(this.user);
  console.log(this.user.get('email'));
  return this;
};

次のように、静的 HTML でアプリケーション コントローラーを初期化します。

jQuery(document).ready(function(){
   window.app = new controllers.Application();
});

提案してください、ありがとうございます!

4

1 に答える 1

3

ここで理解する必要がある2つのことがあります。

  1. fetch非同期です。
  2. 一部console.logは非同期です。

だからこれが起こっていることです:

  1. 呼び出す@user.fetch()と、AJAX呼び出しが開始されます。
  2. あなたが呼び出すconsole.log(@user)と、それは非同期作業の別のビットを行いますが(そしてこれは大きいですが!)、それは@userそれと一緒に参照を取ります、console.log呼び出しがそのロギングを行うときに参照は逆参照されます。
  3. あなたが呼び出すとconsole.log(@user.get('email'))、これは何@user.get('email') が返されるかを引き継ぎ、get呼び出しはすぐに実行されます。
  4. (1)からのA​​JAX呼び出しは、のためにいくつかのものを返します@user
  5. console.log呼び出しは、コンソールに物事を記録するために回避されます。

console.logfrom (2)には、 (4)@userfetch入力されたへの参照が含まれています。(4)が実行されるまでに、が入力されているため、コンソールに完全なユーザーが表示されます。(3)を呼び出すと、まだ入力されていません。実際に入力されているのは@user@user.get('email')fetch@user@user.get('email')undefined

console.log(undefined)

呼び出しの引数は、実行が終了してコンソールに配置されるときではなく、関数を呼び出すときにconsole.log評価されます(ただし、渡される最終結果は逆参照されません!)。console.log

ですから、さまざまな非同期のものが混ざり合っており、そこに混乱があります。

コードを次のように変更した場合:

@user = new models.User
@user.fetch(success: =>
    console.log(@user) 
    console.log(@user.get('email'))   
)

期待どおりの結果が得られます。

于 2012-06-08T06:49:25.833 に答える