Node application interactively get user input from

2019-03-04 04:23发布

问题:

I converted an old game which was written in python to javascript (node). The game simply runs in a while loop until a certain amount of iterations complete.

runUntil(steps = 100000) {
var x = 0;
while (x < steps) {
  this.conversation();
  x++;
}

}

conversation() {
const roundPicture = this.getRandomPicture();
const conversationers = this.utils.getRandomTwo(this.network, this.Graph);

const chosen1 = conversationers[0];
const chosen2 = conversationers[1];


if (chosen1.name == "Player 0" && !chosen1.v.hasOwnProperty(roundPicture)) {
  //Wait for user input
  //..
  //..
  //..
  //Use the given input in order to continue game

}

if (chosen2.name == "Player 0" && !chosen2.v.hasOwnProperty(roundPicture)) {
    //Wait for user input
    //..
    //..
    //..
    //Use the given input in order to continue game

} else {
  //do sth else
}

}

On some occasions, the game pauses in order to get user input which is required and affects the outcome of the game. In my javascript implementation, I used readline-sync to pause the game and get user input through command prompt. Now I built a react front end application in order to serve the game in a browser with UI, and I built a server using express to handle the API and run the game whenever user presses start.

const express = require("express");
const http = require("http");
const socketIO = require("socket.io");
const Game = require("./Game");
const port = 4000;
const app = express();
const server = http.createServer(app);
//Create socket usin server instance
const io = socketIO(server);

io.on("connection", socket => {

  console.log("user connected!");
  socket.on("startGame", data => {
    const nI = data.nI;
    const pI = data.pI;
    const noOfAgents = 20;
    const noOfPlayers = 1;

    const g = new Game(nI, pI, noOfAgents, noOfPlayers);
    g.runUntil(1000);
    });

  socket.on("disconnect", () => console.log("user has disconnected"));
});




server.listen(port, () => console.log("Listenint on port " + port));

However, I am currently stuck at this point. I am not sure how I can pause the game to get the data from the front-end and use it accordingly. All tries I made until now have had no luck. I tried using promises but that didn't help because it didn't paused the process of game flow to wait for user input.

回答1:

There's a convenient package called promise-do-whilst for Node (I'm sure there are other similar analogies for traditional loop constructs organized around Promises. Lets say you have sequential synchronous code that looks like this (where fn is a simple synchronous function):

  do {
    fn();
  } while( condition === true)

... rewrite this as ...

  var promiseDoWhilst = require('promise-do-whilst')
  var condition = true;
  function fn() { // for example
    condition = Math.random() > 0.5; // flip a coin
    return new Promise(function(r, j){
      setTimeout(function(){ r(); }, 1000);
    }); 
  }
  promiseDoWhilst(function() {
    return fn(); with fn converted to a promise-returning function
  }, function() {
    return condition === true;
  })

If you have a couple of parallel threads that you have to wait for to 'make progress' in your loop, you can make them all happen in functions that return promises, put all those returned promises into an array arr, and then have fn return Promise.all(arr). A .then function after a Promise.all receives the resolved values of the original promises in an array preserving the positional order. Hope this helps!