Я создаю игру на угадывание с 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 ответа
Я думаю, это то, что вы ищете:
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>
Используйте 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 () должен установить флаг состояния в объекте context (game) для отправки и отправки на сервер. Когда сервер вернется в функцию ответа, установите состояние ожидающего пользователя и инициируйте соответствующую переменную времени в now (). Функция next_level () должна установить состояние воспроизведения и инициировать соответствующую переменную времени для now (), чтобы таймер мог считать. Рассматривайте приведенный выше код как ссылку, а не как ресурс копирования-вставки.
Кажется, ваш первый вариант работает, если он заключен в асинхронную функцию:
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()
Похожие вопросы
Новые вопросы
javascript
По вопросам программирования на ECMAScript (JavaScript/JS) и его различных диалектах/реализациях (кроме ActionScript). Обратите внимание, что JavaScript — это НЕ Java. Включите все теги, относящиеся к вашему вопросу: например, [node.js], [jQuery], [JSON], [ReactJS], [angular], [ember.js], [vue.js], [typescript], [стройный] и т. д.