现在好几次我遇到了同步和放大的问题。使用Firebase的异步函数。我的问题通常是我需要在我编写的函数中进行异步Firebase调用。举个简单的例子,假设我需要计算&显示对象的速度,我的Firebase存储距离&时间:
function calcVelocity() {
var distance, time, velocity;
firebaseRef.once('value', function(snapshot) {
distance = snapshot.val().distance;
time = snapshot.val().time;
velocity = distance / time;
});
return velocity;
}
$("#velocity").html(calcVelocity());
当然,上述代码无效,因为firebaseRef.once()
是异步调用,因此当我们到达velocity
时尚未设置return velocity;
。如果我们将return
放在.on()
回调函数中,则根本不会返回任何内容。
一种解决方案是使我的calcVelocity()
函数同步。
另一种解决方案是存储同步读取但从Firebase异步更新的Firebase缓存版本。
这些解决方案中的一个比另一个好吗?还有更好的解决方案吗?
答案 0 :(得分:9)
另一种方法是使用Promise策略。 jQuery has a great one
function calcVelocity() {
var distance, time, velocity, def = $.Deferred();
firebaseRef.once('value', function(snapshot) {
distance = snapshot.val().distance;
time = snapshot.val().time;
def.resolve( distance / time );
});
return def.promise();
}
calcVelocity().then(function(vel) { $("#velocity").html(vel); });
请注意,如果snapshot.val().distance;
返回null,snapshot.val()
可能会返回错误!
答案 1 :(得分:8)
您确定了两种可能性:既可以使您的函数异步,也可以缓存最新的Firebase数据,以便您可以同步访问它。考虑到您正在编写的应用程序的上下文,您使用哪一个只是一个偏好和方便的问题。
例如,我们注意到“动作游戏”通常由紧密的渲染循环驱动,而不是由firebase数据更改事件驱动。因此,缓存最新的Firebase数据以便在渲染循环中使用是有意义的。例如:
var latestSnapshot = null;
firebaseRef.on('value', function(snap) { latestSnapshot = snap; });
然后你可以在渲染循环(或其他任何地方)中同步使用latestSnapshot,但是在第一次firebase回调发生之前你需要小心处理它为空。
答案 2 :(得分:6)
与@Kato提供的答案相同,但built-in promises in Firebase看起来像这样
function calcVelocity(snapshot) {
var distance, time, velocity;
distance = snapshot.val().distance;
time = snapshot.val().time;
return distance / time;
}
function getVelocity() {
return firebaseRef.once('value').then(calcVelocity);
}
getVelocity().then(function(vel) { $("#velocity").html(vel); });