2

関数を呼び出して値を取得するハッシュがあります。問題は、関数が本来の値ではなく内部の関数を返していることです。

(ユーザーはこのハッシュの上で定義されます)

私のハッシュ:

userInfo = {
        id: user.id,
        email: user.email,
        cars: getCars(user.id),
      }

この関数を呼び出すもの:

  getCars = (userId) ->
    id = parseInt(userId)
    userRef = new Firebase("https://demo-firebase.firebaseIO.com/users/#{id}/")
    userRef.on('value', (snapshot) ->
      if snapshot.val() == null
        ["toyota"]
      else
        snapshot.val().cars # returns an array of cars
    )

デバッガーで関数をステップ実行すると、ステートメントuserRef.on内の正しい場所ではなく、行に戻ります。if/else

コンパイルされたJSは次のとおりです。

getCars = function(userId) {
  var id, userRef;

  id = parseInt(userId);
  userRef = new Firebase("https://demo-firebase.firebaseIO.com/users/" + id + "/");
  return userRef.on('value', function(snapshot) {
    if (snapshot.val() === null) {
      return ["toyota"];
    } else {
      return snapshot.val().cars;
    }
  });
};

なぜこれが起こっているのですか?私が見落としているのは単純なことだと確信しています。

4

1 に答える 1

6

したがって、firebase から取得するデータはイベント駆動型で非同期であるため、これが同期コードであるかのように返すことはできません。コールバック、プロミス、またはイベント ハンドラーのいずれかを使用する必要があります。

getCars = (userId, callback) ->
  id = parseInt(userId)
  userRef = new Firebase("https://demo-firebase.firebaseIO.com/users/#{id}/")
  userRef.on 'value', (snapshot) ->
    if snapshot.val() == null
      callback ["toyota"]
    else
      callback snapshot.val().cars # returns an array of cars

userInfo = 
  id: user.id
  email: user.email
getCars user.id, (cars) ->
  userInfo.cars = cars
  #Don't user userInfo until here as it's not ready/populated yet!

(ノード規則はcallback(errorOrNull, value)ですが、簡単にするためにここではエラー処理を省略しています)

また、非同期 JavaScript を初めて使用するほとんどすべての人がこの間違いを犯すことに注意してください。ただし、これは単純な構文の落とし穴ではありません。これは、ある時点 (おそらく今日) で、あはは/電球の瞬間を迎える基本的なことです。やるべきことは、これを chrome デバッガーでステップスルーし、コードの各行が時間に関連して実行される順序に注意することです。ステートメントを含む行は、すでに戻ったif後に LATER IN TIME を実行します。getCarsそして、それをステップスルーすると、'value'その行はイベントハンドラーを定義するだけなので、イベントハンドラーの本体をスキップしますが、データが到着するまで実際には実行しないため、その中でデバッグしたい場合は、その関数の最初の行 (ifステートメントがある場所) にブレークポイントを設定する必要があります。

これには、イベント バインディング、プロミス、およびコールバックの 3 つの一般的なパラダイムが使用できます。すべてが機能します。この同じ機能を各パラダイムでコーディングし、基本的にデータの到着を待ってから、データの到着に応じてコードを実行する方法を理解することをお勧めします。

于 2013-07-30T16:20:12.907 に答える