Доброго времени суток.
Пишу юзерскрипт для себя - более удобная читалка
Что за скрипт(страницы - изображения; для каждой страницы есть комментарии; выстраиваю страницы книги на одной странице сайта, при желании можно заглянуть в комментарии к любой странице: почитать, прокомментировать, читать удобнее);
Чтобы сильно не грузить страницу загрузкой своего юзерскрипта делаю все в асинхронных функциях.
Проблема такая, форма запрашивается тоже через ajax {произведение, глава} (в оригинальном исполнении перед каждой отправкой комментария запрашивается одинаковая форма). В скрипте я сразу подгоняю форму под каждую страницу.
Как не слать кучу запросов для получения формы? Понятно, что нужно как-то буферизировать запрос получения формы, а затем отдавать лишь результат. Но функции асинхронные, и перед тем, как ответ придёт, будет отправлено несколько запросов, что может привести к бану.
Разделил запрос формы для страницы на 3 этапа:
- Запрос формы с сервера [1 раз; ограничение на кол-во запросов в сек]
- Косметические изменения [1 раз; изменение общего поведения формы]
- Адаптация формы под конкретную страницу [Множество раз]
Сейчас есть что-то на подобие этого:
const getCommentsInput = (function () {
let commInputBlock = null;
let inition = false;
let commentForm = null;
// Инициализация формы
async function initForm () {
console.log("Inition called!");
inition = true;
const mangaId = $(".reader-controls").html().match(/mangaId=(\d+)/)[1];
const chapterId = $(".reader-controls").html().match(/chapterId=(\d+)/)[1];
commentForm = $.ajax({
type:'POST'
,data:{'mangaId': mangaId,'chapterId': chapterId}
,url:'/internal/modal/addTwittInline'
});
commInputBlock = $("<div>").html(await commentForm);
const frm = commInputBlock.find("form");
frm.attr("onsubmit", frm.attr("onsubmit").replace(".val(rm_h.cur)", ""));
}
// Замыкание для генерации блока формы
return async function (key) {
if (!inition) {await initForm();} // Инициализируем форму при первом запросе
else await commentForm; // Одна из моих попыток ждать конца запроса
const newCommentBlock = commInputBlock.clone();
newCommentBlock.find("#twittPageNumHidden").attr({value: key});
return newCommentBlock.attr({id: `com_input_${key}`});
};
})();
Можно было бы хранить результат вызова initForm() в замыкании и отдавать по первому требованию. При чем возвращать промис: если форма уже получена и подкорректирована, то промис разрешится мгновенно, если нет, то просто await его.
Но тут и так уже куча замыканий в коде, + хранение промиса и возвращение его из асинхронной функции потребует двойного await...
Чувствую иду куда-то не туда. Подскажите, как в буфферизируете большое количество ассинхронных сетевых запросов. Нужно избавиться от повторения, дабы не схлопотать бан.