【问题标题】:Handling Asynchronous Calls (Firebase) in functions在函数中处理异步调用 (Firebase)
【发布时间】:2012-07-23 02:48:56
【问题描述】:

现在我多次遇到使用 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()是一个异步调用,所以当我们到达return velocity;时,velocity还没有被设置。如果我们将return 放在.on() 回调函数中,则根本不会返回任何内容。

一种解决方案是让我的 calcVelocity() 函数也异步。

另一种解决方案是存储 Firebase 的缓存版本,该版本同步读取但从 Firebase 异步更新。

其中一种解决方案是否比另一种更好?有没有更好的解决方案?

【问题讨论】:

标签: javascript ajax asynchronous firebase


【解决方案1】:

另一种方法是利用 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() 返回 null,snapshot.val().distance; 可能会返回错误!

【讨论】:

  • 它使 calVelocity() 同步函数?
  • 至少没有。它使用当数据可用时解决的承诺。
  • 所以它类似于 $loaded in angularfire
【解决方案2】:

您找到了两种可能性:或者使您的函数也异步,或者缓存最新的 Firebase 数据,以便您可以同步访问它。考虑到您正在编写的应用程序的上下文,您使用哪一个只是偏好和方便的问题。

例如,我们注意到“动作游戏”通常由紧密的渲染循环驱动,而不是由 Firebase 数据更改事件驱动。因此,缓存最新的 Firebase 数据以在渲染循环中使用是有意义的。例如:

var latestSnapshot = null;
firebaseRef.on('value', function(snap) { latestSnapshot = snap; });

然后您可以在渲染循环(或其他任何地方)中同步使用 latestSnapshot,但您需要小心处理它为空,直到第一个 firebase 回调发生。

【讨论】:

  • 好主意 - 我没想过只缓存快照。
  • 拯救了我的一天! 4年后的事件!
【解决方案3】:

与@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); });

【讨论】:

  • 不错! Promise 是在 2012 年之后添加的。做了一个快速编辑,因为您过早地调用了 calcVelocity(具有未定义的值)。
猜你喜欢
  • 2018-12-12
  • 2018-03-15
  • 1970-01-01
  • 1970-01-01
  • 2017-08-13
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
相关资源
最近更新 更多