Всё, сделал. (НО не всё понял)
Можно было сразу догадатьсяКак я и думал, проблема в том, что я слишком сильно начал зарываться в замыкания. Из-за длинных цепочек замыканий стало сложно ориентироваться в коде и сказать, как правильно применить async/await (как поведёт себя async/await). Видимо, я всё ещё не до конца осознал механизмы работы async/await, помнил, но не осознал, запамятовал, что async возвращает промис ещё до return (Помнил, но не "дотягивался", банальная мысль).
Как только я осознал, что воюю с async не в те ворота, то всё сразу встало на свои места. Можно было бы потратить пару дней на реализацию подхода с цепочками рекурсии, чтобы вдолбить механизмы его работы себе в голову, но решил не забивать гвозди микроскопом. Раз уж я "дотянулся" до верного механизма async и цепочка действий легла на это поле, то можно просто сделать.
В моём случае, не нужно ждать, пока появится первый запрос на формирование блока комментариев страницы, поэтому достаточно сделать запрос общей формы (первые 2 шага) заранее, запихнуть это в промис и доставать из замыкания уже при появлении запросов.
const getCommentsInputBlock = (function assableCommBlockGenerator() {
// Запрос формы
function requestForm () {
const mangaId = $(".reader-controls").html().match(/mangaId=(\d+)/)[1];
const chapterId = $(".reader-controls").html().match(/chapterId=(\d+)/)[1];
return $.ajax({
type:'POST',
data:{'mangaId': mangaId,'chapterId': chapterId},
url:'/internal/modal/addTwittInline',
});
}
// Косметические правки поведения
async function makeUpForm () {
const commentFormPromise = requestForm();
const commInputBlock = $("<div>").html(await commentFormPromise);
const frm = commInputBlock.find("form");
frm.attr("onsubmit", frm.attr("onsubmit").replace(".val(rm_h.cur)", ""));
return commInputBlock;
}
// Запрашиваем форму заранее - все равно понадобится (промис остаётся в замыкании)
const commInputBlockPromise = makeUpForm();
// Замыкание для генерации блока формы
return async function adaptateFormToPage (key) {
let commInputBlock = await commInputBlockPromise;
const newCommentBlock = commInputBlock.clone();
newCommentBlock.find("#twittPageNumHidden").attr({value: key});
return newCommentBlock.attr({id: `com_input_${key}`});
};
})();
Из-за этого маленького нюанса всё сводится к одному единственному замыканию. Проверка единственности запроса к базе и не нужна вовсе.
Однако я всё ещё не понимаю, как действовать, если мы не можем предугадать запрос заранее, но мы должны обеспечить асинхронность, единственность запроса и гарантировать доступ к полученным данным во всех требуемых местах при актуализации?
Очевидно будет, что выглядеть это должно так, я всё ещё не уверен во всём:
const reqData = await (async function assableRequestor() {
const dataPromises = {};
return async function reqData(params) {
const prmsStr = `${params}`;
if(!dataPromises.includes(prmsStr)) {
const dataPromise = $.ajax(params);
dataPromises[prmsStr] = dataPromise;
return await dataPromise;
}
return await datas[prmsStr];
};
})();
async function doSomething(params) {
let data = await reqData(params);
/*Модификация данных*/
return data;
}
async function doItCool(params) {
let data = await reqData(params);
/*Другая Модификация данных*/
return data;
}
setTimeout(()=>{doSomething(params1)}, 5000);
setTimeout(()=>{doItCool(params1)}, 3000);