在函数中处理异步调用 (Firebase)

声明:本页面是StackOverFlow热门问题的中英对照翻译,遵循CC BY-SA 4.0协议,如果您需要使用它,必须同样遵循CC BY-SA许可,注明原文地址和作者信息,同时你必须将它归于原作者(不是我):StackOverFlow 原文地址: http://stackoverflow.com/questions/11636731/
Warning: these are provided under cc-by-sa 4.0 license. You are free to use/share it, But you must attribute it to the original authors (not me): StackOverFlow

提示:将鼠标放在中文语句上可以显示对应的英文。显示中英文
时间:2020-09-13 16:35:10  来源:igfitidea点击:

Handling Asynchronous Calls (Firebase) in functions

javascriptajaxasynchronousfirebase

提问by Matt Robertson

Several times now I have run into an issue with synchronous & asynchronous functions using Firebase. My problem is often that I need to make an asynchronous Firebase call within a function that I wrote. As a simple example, suppose I need to calculate & display the velocity of an object, and my Firebase stores distance & time:

现在有几次我遇到了使用 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());

Of course, the above code will not work because firebaseRef.once()is an asynchronous call, so velocityhas not been set yet when we reach return velocity;. If we place the returninside the .on()callback function, then nothing is returned at all.

当然,上面的代码不会工作,因为firebaseRef.once()是异步调用,所以velocity我们到达时还没有设置return velocity;。如果我们将return放在.on()回调函数内部,则根本不会返回任何内容。

One solution would be to make my calcVelocity()function asynchronous as well.

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

Another solution would be to store a cached version of the Firebase that is read synchronously but updated asynchronously from the Firebase.

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

Is one of these solutions better than the other? And is there a better solution?

这些解决方案中的一个比另一个更好吗?有没有更好的解决方案?

采纳答案by Michael Lehenbauer

You nailed the two possibilities: Either make your function asynchronous as well, or cache the latest Firebase data so you can access it synchronously. Which one you use is just a matter of preference and convenience, given the context of the app you're writing.

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

For instance, we've noticed that "action games" are usually driven by a tight render loop instead of by firebase data change events. So it makes sense to cache the latest Firebase data for use in your render loop. For example:

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

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

And then you can use latestSnapshot synchronously in your render loop (or wherever else), though you need to be careful to deal with it being null until the first firebase callback happens.

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

回答by Kato

Another approach is to utilize a Promise strategy. jQuery has a great one.

另一种方法是利用 Promise 策略。jQuery 有一个很棒的.

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

Keep in mind also that snapshot.val().distance;may return an error if snapshot.val()returns null!

还请记住,snapshot.val().distance;如果snapshot.val()返回 null ,则可能会返回错误!

回答by Ron Harlev

Same idea as in the answer @Kato provided, but with the built-in promises in Firebasewould look something like this

与@Kato 提供的答案中的想法相同,但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); });