【问题标题】:Asynchronous variables in for loop [duplicate]for循环中的异步变量[重复]
【发布时间】:2017-08-27 09:38:22
【问题描述】:

我正在向我的 chrome 扩展程序添加通知,让用户可以互相聊天。每个用户都有一个chats 部分,其中列出了他们所在的所有聊天室,以及他们看到的最后一条消息。为了检查他们不在时是否发送了消息,我正在尝试遍历他们所在的聊天室,并查看在他们看到的最后一条消息添加后,最后一条发送的消息是否已添加到数据库中。

这是我的代码,我使用的是一个名为 firebase 的 noSQL 数据库:

var checkNotifications = function(user){
   var notification = false;
   firebase.database().ref('users/'+user+'/chats').once('value', function(snapshot){
      for (var chat in snapshot.val()){
         var lastMessage = snapshot.val()[chat];
         firebase.database().ref('chats/'+chat+'/msgs').once('value', function(snap){
            if (Object.keys(snap.val())[0] > lastMessage){
               notification = true;    // Message is newer than their last seen message
            }
         });
      }
   });
}

我遇到的问题是,在第二次数据库调用返回来自当前在 for 循环中查看的聊天室的消息之前,for 循环已经继续前进并更新变量 lastMessage,因此变量结束持有来自聊天室的最后一条消息。

有没有办法减少异步,以便变量 lastMessage 在 for 循环中的每一步都具有相同的值?

【问题讨论】:

  • 这里期望的过程是什么?您想连续迭代并在找到匹配项时停止吗?您想并行迭代并知道是否有任何操作满足您的条件吗?
  • 我的最终目标是获得一个数组,其中每个索引都有truefalse,具体取决于用户看到的最后一条消息之后是否发送了消息,但现在我只想了解在相应聊天室中看到的最后一条消息之后是否发送了任何消息。

标签: javascript firebase asynchronous firebase-realtime-database nosql


【解决方案1】:

要检查是否在他们离开时发送了消息,我正在尝试 遍历他们所在的聊天室并查看最后一条消息 在他们看到的最后一条消息之后发送的被添加到数据库中 已添加。

transactions 具有一个功能,是执行此操作的合适工具。

处理可能被并发破坏的数据时 修改,例如增量计数器,您可以使用事务 手术。你可以给这个操作一个更新函数和一个 可选的完成回调。更新函数采用当前 数据的状态作为参数并返回您想要的新状态 想写。如果另一个客户端之前写入该位置 你的新值被成功写入,你的更新函数被调用 再次使用新的当前值,然后重试写入。 例如,在示例社交博客应用程序中,您可以允许用户为帖子加注星标和取消加注星标,并跟踪帖子获得的星数,如下所示:

function toggleStar(postRef, uid) {
  postRef.transaction(function(post) {
    if (post) {
      if (post.stars && post.stars[uid]) {
        post.starCount--;
        post.stars[uid] = null;
      } else {
        post.starCount++;
        if (!post.stars) {
          post.stars = {};
        }
        post.stars[uid] = true;
      }
    }
    return post;
  });
}

【讨论】:

    【解决方案2】:

    这应该可以。它在闭包中捕获变量:(function(){ ... })();

    var checkNotifications = function(user){
        var notification = false;
        firebase.database().ref('users/'+user+'/chats').once('value', function(snapshot){
            for (var chat in snapshot.val()){
                (function(){
                    var lastMessage = snapshot.val()[chat];
                    firebase.database().ref('chats/'+chat+'/msgs').once('value', function(snap){
                        if (Object.keys(snap.val())[0] > lastMessage){
                            notification = true;    // Message is newer than their last seen message
                        }
                    });
                })();
            }
        });
    }
    

    或者这个:

    var checkNotifications = function(user){
        var notification = false;
        firebase.database().ref('users/'+user+'/chats').once('value', function(snapshot){
            var func = function(lastMessage) {
                firebase.database().ref('chats/'+chat+'/msgs').once('value', function(snap){
                    if (Object.keys(snap.val())[0] > lastMessage){
                        notification = true;    // Message is newer than their last seen message
                    }
                });
            };
            for (var chat in snapshot.val()){
                func(snapshot.val()[chat]);
            }
        });
    }
    

    【讨论】:

    • 但是,这没有可靠的地方来评估 notification 标志,因为操作是异步的。您不能只在for 循环结束时检查该标志。异步操作尚未完成。这将无法正常工作。
    • 你是对的。我错过了那部分。 notification 标志在代码中无效。一种解决方案可能是将回调函数传递给在 func() 的最后一次迭代之后调用的 checkNotifications,这可以通过计数器变量来确定。
    猜你喜欢
    • 1970-01-01
    • 2016-05-03
    • 1970-01-01
    • 2017-02-25
    • 1970-01-01
    • 1970-01-01
    • 2013-06-24
    相关资源
    最近更新 更多