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 新手都会犯这个错误,但这不是一个简单的语法陷阱,它是一个基本的事情,你在某个时候(也许今天)你会拥有 aha/lightbulb 时刻。要做的事情是在 chrome 调试器中逐步执行此操作,并注意每行代码时间相关的执行顺序。带有语句的行在已经返回if之后执行 LATER IN TIME 。getCars请注意,如果您单步执行它,它将直接跳过'value'事件处理程序的主体,因为该行只是定义事件处理程序,但在数据到达之前它实际上并没有执行它,所以如果您想在其中进行调试,您需要在该函数的第一行(if语句所在的位置)设置断点。

有 3 种常见的范例可用:事件绑定、承诺和回调。一切都会奏效。使用每个范例编写相同的功能对您来说是一个很好的练习,并了解它们基本上都为您提供了一种等待一些数据到达然后运行一些代码以响应数据到达的方法。

于 2013-07-30T16:20:12.907 回答