Make this function synchronous?

1k views Asked by At

I'm running the following bit of code to get input from the terminal in nodejs (I picked this method because it doesn't need dependencies) and I need it to work synchronously. It's inside a function that gets called repeatedly by a for loop and thus in its current async state it's causing some problems.

Here's the function that i'd like to make synchronous:

standard_input.on('data', function (data) {
 choice = data;
 if (choice == 1) response = rp.r1;
if (choice == 2) response = rp.r2;


console.log("[" + character.name + "]: " + response);
});

Thanks for your help!

EDIT: More detailed explanation of my situation and code as follows:

I have a for loop that calls a synchronous function, conversation(). In this function there is a section of code which requires that the for loop halt until the user has input something. I'm asking for a way to do that either with my existing method of getting user input (shown above) or a different one.

EDIT 2: THE SEQUEL:

More complete snippet of my code to help with answers, as some of the provided answers don't work for me because I wasn't clear enough about what I'm trying to do.

function conversation(character, num, rp) {
if (negStreak >= 4) {
  return false;
}
var choice;
var response;

console.log("CHOICES:");
console.log("(1): " + rp.c1);
console.log("(2): " + rp.c2);
console.log("Type 1 or 2 and hit Enter.");

standard_input.on('data', function (data) { //this is how i'm getting input
 choice = data;
 if (choice == 1) response = rp.r1;
if (choice == 2) response = rp.r2;
negStreak++

console.log("[" + character.name + "]: " + response);
});

}

function game(char) {
  negStreak = 0;
if (char.name == "Vern") array = vern_conv;
if (char.name == "Jericho") array = jericho_conv;
if (char.name == "Las") array = las_conv;
if (char.name == "char3") array = char3_conv;
if (char.name == "char4") array = char4_conv;

for (i = 0; i < array.length; i++) { //this is the for loop i'm talking about
var reactionPair = array[i];
conversation(char, i, reactionPair);
}
}
2

There are 2 answers

4
Sven.hig On

if understood what you need correctly you will need to use async and await to wait for the data to be assigned in your function so you may want to try something like this

    async function userinput(){
   return await new Promise(resolve=>{
    standard_input.on('data', function passdata (data) {
      standard_input.removeEventListener("data",passdata);

      choice = data;
      if (choice == 1) resolve(response = rp.r1);
     if (choice == 2) resolve(response = rp.r2)
     console.log("[" + character.name + "]: " + response);
     });
  })
}
userinput()
0
danh On

Instead of wrapping your input in a for loop...

for (loop var) {
  input = prompt_for_input <--- oh no, this is inherently async
  do something with input
}

make your loop iterate as a result of input, so it looks like this...

prompt_for_input
whenWeGetInput(
  do something with input
  prompt_for_input // <-- this is your loop now
) 

nodejs readline allows for this kind of loop using createInterface...

const readline = require('readline')
let rl = readline.createInterface(process.stdin, process.stdout)

rl.setPrompt('$ ')
rl.prompt()

rl.on('line', choice => {
  switch(choice.trim()) {
    case '1':
      console.log('you typed 1')
      break
    case '2':
      // and so on
    default:
      console.log(`you typed something else: ${choice}`)
      break
    }
    rl.prompt() // <-- this is your loop now
}).on('close', () => {
  process.exit(0)
})