Сделать отображение страницы 10 секунд в цикле - PullRequest
0 голосов
/ 28 октября 2019

Я строю игру на угадывание с Node JS. После сбора некоторых данных на бэкэнде, я отправляю их на фронтэнд, и игра начинается. Данные содержат все 10 уровней, поэтому игра может запускаться на одной странице. Каждый уровень длится 10 секунд. После истечения времени выбор пользователя отправляется на сервер, и результат возвращается. Отображается ответ, а затем содержимое изменяется на «следующий уровень» (с использованием содержимого в большом объекте данных, поэтому обновление не требуется).

У меня возникают проблемы с запуском 10 уровней по 10 секунд каждый (или ~ 12 секунд с задержкой для отображения результатов).

Этого нельзя сделать в каком-то цикле, так как все awaits для каждого уровня будут выполняться одновременно. Например:

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);
}

все timeout будут работать одновременно, и это не будет работать.

Я думал об использовании setInterval, но я неконечно, как ... так как я хочу подождать 10 секунд до проверки ввода, а затем отобразить результаты в течение 2 секунд, а затем перейти к следующему.

На данный момент я получил следующий результат:

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);

...

Это не кажется эффективным, и я думаю, что есть лучший способ сделать это, но я не уверен, как. Мы ценим любые предложения. Спасибо!

Ответы [ 3 ]

0 голосов
/ 28 октября 2019

используйте setInterval на 1000 мс, чтобы создать работника и добавить конечный автомат, который переключает воспроизведение (10 с) и ожидание (2 с). Вам нужна процедура, которая выполняет пост-вызов на сервер и объект для хранения данных (уровней и прочее).

, например:

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 () должен установитьфлаг состояния в контекстном (игровом) объекте, отправлять и отправлять на сервер. Когда сервер вернется в функцию ответа, установите состояние ожидающего пользователя и инициируйте соответствующую переменную времени в now (). Функция next_level () должна установить состояние воспроизведения и инициировать соответствующую переменную времени для now (), чтобы таймер мог считать. Рассматривайте приведенный выше код как ссылку, а не как ресурс копирования-вставки.

0 голосов
/ 28 октября 2019

Я думаю, это то, что вы ищете:

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>

Другое решение, без обещаний и петель:

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 голосов
/ 28 октября 2019

Кажется, что ваш первый вариант работает, если он заключен в асинхронную функцию:

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()
...