1

I'm trying to make an event driven while loop in javascript. Essentially it iterates through an array of values and makes a query during each iteration. Then, based on the result of the query it should either keep looping or stop and do something.

I realize that you can't have callbacks in a while loop so I'm confused on how to even implement such a thing. Nested functions repeat themselves and that's not ideal.

my loop code:

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

3 Answers3

3

You should use recursion. An approach to that would be something like this:

     function next() {

            // ....

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

     next();

Of course this is just an example. You should adapt it to you entire code.

Pablo Matias Gomez
  • 6,614
  • 7
  • 38
  • 72
  • I was doing the same thing earlier but when it finally finishes, the function is still being called. I console log `done` when it it goes into the success block but `done` is being logged more than once. I'm assuming the function is still being called even after it reaches done. – Pj Rigor Dec 16 '16 at 00:22
  • the only reason the function would be called is if `reply.success` is false - the only way you'd keep on getting done logged is if the callback to `bridgeCheckRooms` is called multiple times by `bridgeCheckRooms` - explain a little about `bridgeCheckRooms` and how the callback is used by that function – Jaromanda X Dec 16 '16 at 00:28
  • the bridge function emits a socket message with the room to be queried. after the room has been found or found empty, the server sends back an answer which is then sent back to the original function. here's the code for the bridge: `function bridgeCheckRooms(send,callback){ socket.emit('room-check',send); //when room has been retrieved socket.on('room-checked'+send.id,function(reply){ callback(reply); }); }` not too sure if it will format correctly – Pj Rigor Dec 16 '16 at 00:32
  • so it's not possible that `socket.on('room-checked'+send.id, ` is being triggered more than once? – Jaromanda X Dec 16 '16 at 00:34
  • this solution works, however the function is executing more than once somehow but it indeed stops sending calls to bridgeCheckRooms after a successful reply – Pj Rigor Dec 16 '16 at 00:54
1

Your code would be correct if bridgeCheckRooms was synchronous and blocked the thread of execution until the response was returned. See this SO post on synchronicity

Here is what is happening in your code:

The code block in your while loop is executing bridgeCheckRooms which we will assume does some work, then queues an asynchronous call to the database. bridgeCheckRooms will then return, and execution of your while loop will immediately continue, and queue up yet another call to bridgeCheckRooms.

They key piece is that bridgeCheckRooms is an asynchronous function, and doesn't block execution until it is finished. So when you call bridgeCheckRooms, it simply queues an asynchronous call, but doesn't wait until it completes.

So if your while loop executes 10 times, you will have 10 pending requests to the database. But those requests won't get to execute until the while loop stops executing and yields execution for the asynchronous queue to execute.

@pablo has the right code approach for this. The difference between his code and your code, is that a second asynchronous call is not made until the first asynchronous call has completed.

Edit: CallbackHell.com looks like a great primer on this topic

Community
  • 1
  • 1
Sam
  • 1,052
  • 11
  • 17
0

I think you want to look into deferred objects and promises. You want to wait until the async call is done to make your check to see if you need to keep looping.

Or you could make it a synchronous call if there is not benefit to the async here.

Learning2Code
  • 521
  • 9
  • 21
  • 2
    This would be better as a comment, unless you add some code to back up your assertion that Promises would be useful – Jaromanda X Dec 16 '16 at 00:14
  • 2
    in browsers, synchronous network requests are deprecated on the main thread, so if this is browser code (and there's no indication that it's NOT) that's a poor suggestion – Jaromanda X Dec 16 '16 at 00:20