Задать вопрос
Ответы пользователя по тегу JavaScript
  • Как буфферизировать ajax-запросы в async-функциях?

    MaxLevs
    @MaxLevs Автор вопроса
    Всё, сделал. (НО не всё понял)
    Можно было сразу догадаться
    Как я и думал, проблема в том, что я слишком сильно начал зарываться в замыкания. Из-за длинных цепочек замыканий стало сложно ориентироваться в коде и сказать, как правильно применить 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);
    Ответ написан
    Комментировать
  • Присвоить значение через аргумент?

    MaxLevs
    @MaxLevs
    Использовать ссылочные типы.
    let bufer = {};
    function foo(buf, a, b) {
        buf.foo_ans = a + b;
    }
    function bar(buf, a, b) {
        buf.bar_ans = a * b;
    }
    foo(bufer, 3, 5);
    bar(bufer, 3, 5);
    console.log(bufer); //{foo_ans: 8, bar_ans: 15}
    Ответ написан
  • Парсинг HTML без подгрузки данных по ссылкам?

    MaxLevs
    @MaxLevs Автор вопроса
    Вопрос снят. Решил не вставлять все налево и направо, а просто использовать регулярки.
    Если кому интересно (лол), вот код:
    var news_id = window.location.pathname.match(/\d*-/)[0].match(/\d*/)[0];
    var bestComm = document.getElementsByClassName('comm_best')[0].children;
    var bestCommsIds = [];
    var lastPage =  document.getElementsByClassName('navigation')[0].lastElementChild.innerHTML;
    var compl = 0;
    lastPage = parseInt(lastPage, 10);
    for (var i = 0; i < bestComm.length; ++i) {
        bestCommsIds.push(new RegExp(bestComm[i].id));
    }
    
    function getCommentPage(page) {
        $.get(dle_root+"engine/ajax/comments.php", {cstart:page,news_id:news_id,skin:dle_skin}, function(data){
            for(i = 0; i < bestCommsIds.length; ++i){
                if (data.comments.match(bestCommsIds[i])){
                    bestComm[i].onclick = function(){CommentsPage(page, news_id); return false;};
                    if(++compl === bestCommsIds.length){
                        return 0;
                    }
                }
            }
        },"json");
    }
    
    for(var page = 1; page < lastPage; ++page){
        getCommentPage(page);
    }
    Ответ написан
    Комментировать