Estoy construyendo un juego de adivinanzas con Node JS. Después de recopilar algunos datos en el back-end, los envío al front-end y comienza el juego. Los datos contienen los 10 niveles, por lo que el juego puede ejecutarse en una sola página. Cada nivel se ejecuta durante 10 segundos. Después de que se acabe el tiempo, la selección del usuario se envía al servidor y se obtiene un resultado. Se muestra la respuesta y, a continuación, el contenido se cambia al "siguiente nivel" (utilizando el contenido en el objeto de big data, por lo tanto, no es necesario actualizarlo).

Tengo algunos problemas con la ejecución de 10 niveles durante 10 segundos cada uno (o ~ 12 segundos con un retraso para mostrar los resultados).

Esto no se puede hacer en algún tipo de bucle, ya que todos awaits para cada nivel se ejecutarán a la vez. Por ejemplo:

function timeout(ms) {
    return new Promise(resolve => setTimeout(resolve, ms));
}

for (let i = 0; i < 10; i++) {
    displayPage(i);
    await timeout(10000);
    const result = await $.post(...) // gets results
    displayResults(result);
    await timeout(2000);
}

Todos los timeout s se ejecutarán a la vez y no funcionarán.

Pensé en usar un setInterval, pero no estoy seguro de cómo hacerlo ... ya que quiero esperar 10 segundos hasta verificar la entrada, y luego mostrar los resultados durante 2 segundos, y luego seguir adelante.

Por ahora, el resultado que se me ocurrió es:

displayPage(level1);
await timeout(10000);
const result = await $.post(...)
displayResults(result);
await timeout(2000);

displayPage(level2);
await timeout(10000);
const result = await $.post(...)
displayResults(result);
await timeout(2000);

displayPage(level3);
await timeout(10000);
const result = await $.post(...)
displayResults(result);
await timeout(2000);

displayPage(level4);
await timeout(10000);
const result = await $.post(...)
displayResults(result);
await timeout(2000);

...

Esto no parece eficiente y creo que hay una mejor manera de hacerlo, pero no estoy seguro de cómo hacerlo. Cualquier sugerencia sera apreciada. ¡Gracias!

0
ethanpasta 28 oct. 2019 a las 00:08

3 respuestas

La mejor respuesta

Creo que esto es lo que estás buscando:

const pages = [1, 2, 3, 4, 5];

run();

async function run() {
  for (let i = 0; i < pages.length; i++) {
    await displayPage(i);
    const result = 'Some result';
    await displayResult(result);
  }
}

function displayPage(number) {
  text.innerText = 'Page ' + number;

  return new Promise(res => {
    setTimeout(res, 10000);
  });
}

function displayResult(result) {
  text.innerText = 'Result: ' + result;

  return new Promise(res => {
    setTimeout(res, 2000);
  });
}
<div id="text"><div>

Otra solución, sin promesas y lazos:

const pages = [1, 2, 3, 4, 5];
let currentPageIndex = 0;

displayPage();

function displayPage() {
  const index = currentPageIndex++;
  if (pages[index] === undefined) return;

  const pageNumber = pages[index];

  text.innerText = 'Page ' + pageNumber;

  const result = 'Some result';

  setTimeout(() => {
    displayResult(result);
  }, 10000);
}

function displayResult(result) {
  text.innerText = 'Result: ' + result;

  setTimeout(() => {
    displayPage();
  }, 2000);
}
<div id="text"></div>
0
Andrew Dashkov 27 oct. 2019 a las 22:38

Use setInterval en aproximadamente 1000 ms para crear un trabajador y agregue una máquina de estado que alterna la reproducción (10s) y la espera (2s). Necesita un procedimiento que realice la llamada posterior al servidor y un objeto para mantener los datos (niveles y demás).

Por ejemplo:

setInterval(funcWorker,1000,s_gameObj);



 function funcWorker(f_context){
    var l_dateNow = new Date();
    if(f_context.is_playing){
       var l_elapsed = l_dateNow.getTime() - f_context.dateLevelStart.getTime();
       if(l_elapsed.totalSeconds() >= f_context.LEVEL_TIME){

           f_context.end_level();
       }
    }else if(f_context.is_waiting_user){
       //same check as above but on the waiting start 
        ....
         f_context.next_level();


    }else if(f_context.is_waiting_server){
       //do whatever
    }
}

End_level () debe establecer el indicador de estado en el objeto de contexto (juego) para enviar y enviar al servidor. Cuando el servidor regrese en la función de respuesta, establezca el estado en espera del usuario e inicie la variable de tiempo correspondiente a now (). Next_level () debe establecer el estado en reproducción e iniciar la variable de tiempo correspondiente a now () para que el temporizador pueda contar. Considere el código anterior como referencia y no como un recurso de copiar y pegar.

0
t.stv 27 oct. 2019 a las 21:45

Su primera opción parece funcionar asumiendo que está envuelta dentro de una función asíncrona:

function timeout(ms) {
    return new Promise(resolve => setTimeout(resolve, ms));
}
const testFunc = async () =>{
  for (let i = 0; i < 10; i++) {
      console.log('page' , i+1 , '- question')
      await timeout(3000);
      console.log('page' , i+1 , '- answer')
      await timeout(1000);
  }
}
testFunc()
0
Willman.Codes 27 oct. 2019 a las 21:27