【问题标题】:Javascript callback within a while loop does not work?while 循环内的 Javascript 回调不起作用?
【发布时间】:2017-05-01 17:11:48
【问题描述】:

我正在尝试在 javascript 中创建一个事件驱动的 while 循环。本质上,它遍历一组值并在每次迭代期间进行查询。然后,根据查询的结果,它应该继续循环或停止并做一些事情。

我意识到你不能在 while 循环中进行回调,所以我对如何实现这样的事情感到困惑。嵌套函数会重复自己,这并不理想。

我的循环代码:

             var done = false;
             while(!done){
                bridgeCheckRooms(send,function(reply){ //callback
                    console.log(tagArray[count]);
                    console.log(reply);
                    if(reply.success){
                        done = true;
                    } else {
                        count--;
                    }
                });
            }

【问题讨论】:

  • 你应该在“未完成”时再次调用自身而不是循环
  • 换句话说,你需要研究递归
  • bridgeCheckRooms 是否进行异步调用?
  • 我这样做了,但即使done==true,该函数最终也会多次复制,因此它运行的次数超出了我的需要。
  • 是的,bridgeCheckRooms 函数确实对数据库进行了异步调用以获取值。 @Learning2Code

标签: javascript asynchronous while-loop callback iteration


【解决方案1】:

如果bridgeCheckRooms 是同步 并且阻塞执行线程直到返回响应,您的代码将是正确的。看到这个SO post on synchronicity

以下是您的代码中发生的情况:

while 循环中的代码块正在执行bridgeCheckRooms,我们假设它做了一些工作,然后对数据库的异步调用进行排队。然后bridgeCheckRooms 将返回,您的while 循环将立即继续执行,并排队再次调用bridgeCheckRooms

他们的关键部分是bridgeCheckRooms 是一个异步函数,在完成之前不会阻塞执行。因此,当您调用 bridgeCheckRooms 时,它只是将异步调用排队,但不会等到它完成。

因此,如果您的 while 循环执行 10 次,您将有 10 个 待处理 对数据库的请求。但是这些请求在 while 循环停止执行并让异步队列执行之前不会执行。

@pablo 对此有正确的代码方法。他的代码和您的代码之间的区别在于,在第一次异步调用完成之前不会进行第二次异步调用。

编辑:CallbackHell.com 看起来是这个主题的一个很好的入门书

【讨论】:

    【解决方案2】:

    我认为您想研究延迟对象和承诺。您想等到异步调用完成后再检查是否需要继续循环。

    或者,如果这里的异步没有好处,您可以将其设为同步调用。

    【讨论】:

    • 这作为注释会更好,除非你添加一些代码来支持你的断言,即 Promises 会很有用
    • 在浏览器中,同步网络请求在主线程上被弃用,所以如果这是浏览器代码(并且没有迹象表明它不是),这是一个糟糕的建议
    【解决方案3】:

    你应该使用递归。一种方法是这样的:

         function next() {
    
                // ....
    
                bridgeCheckRooms(send,function(reply){ //callback
                    console.log(tagArray[count]);
                    console.log(reply);
                    if(reply.success){
                        // continue() ?
                        // done = true;
                    } else {
                        count--;
                        next();
                    }
                });
         }
    
         next();
    

    当然这只是一个例子。你应该让它适应你的整个代码。

    【讨论】:

    • 我之前也在做同样的事情,但是当它最终完成时,该函数仍在被调用。我控制台记录done 当它进入成功块但done 被记录不止一次。我假设该函数在完成后仍然被调用。
    • 函数被调用的唯一原因是如果reply.success 是假的 - 你继续完成记录的唯一方法是如果bridgeCheckRooms 的回调被@987654326 多次调用@ - 解释一下 bridgeCheckRooms 以及该函数如何使用回调
    • 桥接函数发出一个带有要查询的房间的套接字消息。在房间被找到或发现是空的后,服务器发回一个答案,然后将其发回原来的函数。这是桥的代码:function bridgeCheckRooms(send,callback){ socket.emit('room-check',send); //when room has been retrieved socket.on('room-checked'+send.id,function(reply){ callback(reply); }); } 不太确定它是否会正确格式化
    • 所以socket.on('room-checked'+send.id, 不可能被多次触发?
    • 此解决方案有效,但该函数以某种方式执行了多次,但在成功回复后确实停止向 bridgeCheckRooms 发送调用
    猜你喜欢
    • 2015-03-09
    • 1970-01-01
    • 2023-03-29
    • 1970-01-01
    • 2011-10-19
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2022-01-26
    相关资源
    最近更新 更多