我有一个调用函数来获取值的哈希。问题是,函数返回内部函数而不是它应该的值。
(用户定义在此哈希之上)
我的哈希:
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;
}
});
};
为什么会发生这种情况?我确信这是一个简单的东西,我忽视了。
答案 0 :(得分: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)
,但为了简单起见,我省略了错误处理)
另请注意,几乎所有对async javascript都不熟悉的人都会犯这个错误,但这并不是一个简单的语法问题,在某些时候(也许是今天),你将拥有aha / lightbulb时刻是一个基本的东西。要做的是在chrome调试器中逐步执行此操作,并注意与时间相关的命令执行每行代码。在if
已经返回后,getCars
语句的行执行时间过长。请注意,如果你单步执行它,它将跳过'value'
事件处理程序的主体,因为该行只是定义事件处理程序,但它实际上并不执行它直到数据到达,所以如果你想调试,你需要在该函数的第一行设置一个断点(if
语句所在的位置)。
有三种常见的范例:事件绑定,承诺和回调。一切都会奏效。对每个范例编写相同的功能并理解它们基本上都可以让您等待一些数据到达然后运行一些代码以响应数据到达,这将是一个很好的练习。