Дорогие друзья, товарищи, коллеги. Есть вопрос по JS, в данное время нет идей, как можно реализовать + опыт пока не очень (но я стараюсь, честно).
Кто-нибудь в ходе практики сталкивался с такой задачей:
- есть несколько функций, которые должны выполняться одна за другой
- в ходе их выполнения происходит взаимодействие с пользователем (т.е. ему нужно что-то ввести, какую-то кнопку нажать).
- осложняется это тем, что события в функции должны быть рандомными (т.е. есть массив объектов, которые содержат в себе данные и функцию для работы с ними).
Суть такова: эти функции выводят в элемент DOM вопросы с вариантами ответов. На данном этапе у меня получается так, что они разом выводятся в этот div и всё. А хотелось бы, чтобы следующая функция не выводилась до тех пор, пока текущая не получит ответ от пользователя. Т.е. чтобы основной поток находился в режиме ожидания до взаимодействия.
Оговорюсь сразу - использовать prompt и confirm не является решением.
Пока я решил проблему так, что нужная следующая функция вызывается в конце текущей. Но такой подход, на мой взгляд, в корне неверен.
Сейчас функций мало, массив небольшой. А если их будет большее количество (20, например) - могут возникнуть определенные сложности + если мы будем вызывать эту функцию из массива, то после неё будет исполняться следующая, что совершенно не приемлемо.
Подождите, прежде чем дать какой-то ответ/решение к задачи - нужно понять суть проблемы.
Прежде всего давайте разбираться с проблематикой.
Вам нужно, чтобы по событию вызывалась функция, в которой будут в определенном порядке вызываться три остальные? Причем этих остальных функций может быть N-ое количество и вызываться они должны в строгом порядке и только друг за дружкой?
Или Вам нужно показывать модальные окна, после завершения обработки каждого из которых будет вызываться следующее?
Потому что это две совершенно разные задачи и совершенно не обязательно придумывать что-то с промисами для того, чтобы вызывать друг за дружкой модальные окна.
Ну есть у Вас N-массивов, в каждом лежит сколько-то функций. В какой-то момент Вам нужно вызывать из каждого массива, по одной функции, по очереди, причем одну после другой - ну так это называется стек. Кладёте в какой-то стек указатели на объекты функций при вызове вашей основной, а потом по событию из модалок шифтите( вытаскиваете из начала ) по одной и выполняете.
Вам можно разделить отрисовку модалок или просто сделать функцию, которая будет извлекать из стека следующую и вызывать.
Вот пример с комментариями.
Но сразу хочу сказать, что это просто один из вариантов решения. Всё это конечно же можно сделать на промисах.
Пример реализации, которую я показал плоха хотя бы тем, что есть глобальные объекты, что всегда нежелательно.
Почитал комментарии и понял, что хорошим тоном будет добавить пример реализации на промисах.
За основу я взял код из фидла Сергей delphinpro совсем чуть-чуть модифицировал и добавил исчерпывающих комментариев.
И вот еще мой фидл, который я сделал параллельно, там пример "промисификации" функции.
Конечно, хорошо бы еще на async/await всё это дело сделать ради примера)
function a() {}
function b() {}
function c() {}
let fn_arr = [a,b,c]; //Массив функций
let current = 0;
function onclick() { //Событие
fn_arr[current]();
current++;
if (current == fn_arr.length) current = 0;
}
Для реализации тестов (вы же это делаете? что-то типа тестов — последовательные вопросы с ответами) Вам достаточно две функции, показать вопрос и вывести результат.
Все остальное - это массив данных.
Есть массив данных, есть указатель текущего вопроса.
Указатель изначально указывает на первый вопрос.
Показываем этот вопрос.
Получаем ответ, сохраняем, увеличиваем указатель на единицу.
Показываем этот вопрос.
Получаем ответ, сохраняем, увеличиваем указатель на единицу.
…
Показываем результат.
Эх, если бы это было столь же просто, то это было бы хорошо. Опишу чуть подробнее:
- есть основная функция, которая при определённом событии запускает цепь из 3 функции
- каждая функция - это случайное событие, которое вызывается случайно из массива (у каждой из функции - свой массив)
- результат обработки данных выводится в диалоговое окно
- мы ждем, пока пользователь прореагирует с этим окном (это может быть просто его закрытие или выбор вариантов), и только после этого переходим к следующей функции.
Т.о. мы получаем 3 последовательных диалоговых окна. Если сделать вот так:
float() {
func1();
func2();
func3();
};
то эти три функции по очереди отрисуют 3 модальных окна и всё. С одной стороны - можно это оставить и так, но желательно добиться последовательного выполнения. В настоящий момент используется вот такая конструкция:
float() {
func1() {
здесь вызываем функцию случайного объекта массива 1,
в конце которой вызываем func2() {
здесь вызываем функцию случайного объекта массива 2,
в конце которой вызываем func3() {
здесь вызываем функцию случайного объекта массива 2,
в конце которой уже ничего не вызываем
};
};
};
Анатолий Куликов, пока не вижу разницы, кроме более сложной обработки данных. Если у вас количество шагов не фиксированно, то такой подход не подходит, он плохо расширяем. Нужно все сводить к циклической обработке. И задействовать промисы.