hplus0606 makes a good point -- most networking is asynchronous otherwise you'd be locking up the machine any time you made even a basic request. That's just a bad idea for many reasons.
That being said, you're also correct that on servers there are typically synchronous and asynchronous socket types available. On a client, however, you should never be able to easily lock up the user's machine!
Because client-side is mostly asynchronous, you need to put your code into event handlers. Here's a sample from Mozilla (but most JavaScript implementations will be similar):
var exampleSocket = new WebSocket("someserver.com");
exampleSocket.onmessage = function (event) {
console.log(event.data);
}
In practical terms this means that you can't put all of your game actions into a single processing loop (that's actually a bad way to code anyways -- makes it very difficult to upgrade and maintain).
So how can you process game actions? Without knowing specifics, there are two general approaches you can take:
1. Put your game handling code into a single "processGameAction" function (or something similar), and invoke it when you get the response:
exampleSocket.onmessage = function (event) {
processGameAction();
}
The processGameAction function could create timers to control independent game elements so that game action could continue even between socket messages.
2. Do the same thing as above but instead of calling processGameAction from the event handler, you would set the current game state in the handler and instead keep processGameAction running in an indefinite loop (timer).
var gameState={};
gameState.queue=false;
exampleSocket.onmessage = function (event) {
gameState.action=event.someData; //Just an example...you need to grab the relevant values yourself...
gameState.queue=true;
}
function processGameAction() {
if ((gameState==null) || (typeof gameState=="undefined")) {
return;
}
if (gameState.queue==false) {
return;
}
if (gameState.action=="doStuff") {
//do stuff here
gameState.queue=false; //Make sure we only process this once after being set!
}
}
window.setInterval(processGameAction,10); //Execute every 10 ms
The "doStuff" part above is, again, up to you. In fact, the gameState object is completely open-ended -- you fill it with the data that you need based on the socket or user interaction events within the game.
The main idea here is that you need to encapsulate your game logic within a function and, at the very least, call that function on a timer in order to create a loop. This also means having to potentially create additional variables to track your loop state, but that's really part and parcel of Object-Oriented(ish) Programming.
Keep in mind that you can create numerous timers -- just make sure to store their IDs (the setInterval function returns this), so that you can stop/restart them when needed. This is a bit more complex than just straight-up procedural loops but it gives your WAY more flexibility without locking up your code (for example, your intervals can be set to trigger at various rates depending on how fast you want the game to move).