Сгенерировать отправку нескольких форм одновременно в JavaScript

Вопрос или проблема

У нас в школе есть старая образовательная платформа с низкой удобочитаемостью. Я стараюсь улучшить её, написав дополнение для себя и своих коллег. Мне удалось сделать несколько вещей, но я застрял, пытаясь отправить несколько форм одновременно. Задача следующая: на веб-странице есть список всех моих студентов. Для каждого из них предусмотрено текстовое поле для оценивания и ссылка “Сохранить”, которая обновляет и устанавливает текущее время и дату в качестве временной метки для текста.

Ссылка вызывает метод, который копирует некоторые параметры в форму и отправляет её. Это известно как механизм постбека Asp.net (функция doPostBack).

Я хотел бы запустить это в цикле для всех студентов, чтобы каждое оценивание, даже пустое, получало новую временную метку, просто чтобы подтвердить, что старая оценка всё ещё действительна.

У меня есть работающий цикл, но только первая отправка проходит успешно. Это связано с тем, что отправка вызывает полный запрос и страница перезагружается —> Цикл останавливается.

Обходной путь: скрипт копирует форму в iframe, чтобы предотвратить перезагрузку. Работает, но теперь проблема в том, что обновляется только последний студент в цикле.

Я думал, что дело в тайминге, запросы поступают слишком быстро для сервера. Поэтому я замедлил это до 5 секунд ожидания между запросами, но только у последнего студента отображается обновлённая временная метка.

Мне нужна ещё одна идея для решения этой проблемы. Вот мой код на данный момент. count и if(count<3) только для отладки:

document.getElementById('saveAll').addEventListener('click', () => {
    addText = document.getElementById('add2BoxText').value;

    chrome.tabs.query({
        active: true,
        currentWindow: true
    }, (tabs) => {
        chrome.scripting.executeScript({
            target: {
                tabId: tabs[0].id
            },
            function: saveAllBoxes

        });
    });
});

function saveAllBoxes() {

    var c = 0;
    var theForm = document.forms['aspnetForm'];

    const iframe = document.createElement('iframe');

    iframe.style.display = 'none';
    document.body.appendChild(iframe);
    const formClone = theForm.cloneNode(true);
    iframe.contentDocument.body.appendChild(formClone);
    
    if (!formClone) {
        formClone = document.aspnetForm;
    }

    async function __doPostBack(eventTarget, eventArgument) {
        if (!formClone.onsubmit || (formClone.onsubmit() != false)) {
            formClone.__EVENTTARGET.value = eventTarget;
            formClone.__EVENTARGUMENT.value = eventArgument;

            formClone.submit();
            console.log(formClone.__EVENTTARGET.value);
            c++;
        }
    }

    count = 0;
    var all_td_a = document.querySelectorAll('td a');
    
    all_td_a.forEach((element) => {

        if (element.text == 'Spara') {
            element.text = "Saved";
            fullLink = element.href;
            var fullLink = fullLink.substring(fullLink.indexOf("'") + 1, fullLink.lastIndexOf("'") - 3);
            nu = new Date().valueOf() + 2500;
            console.log('---',nu);
            while (nu > new Date().valueOf()) {
            }
            console.log(new Date().valueOf());
           if(count < 3) __doPostBack(fullLink, '');
            count++;
        }
    });
   
}

Ответ или решение

Конечно! Давайте рассмотрим, как можно решить вашу задачу по одновременному обновлению нескольких форм на веб-странице, используя JavaScript и механизмы асинхронного программирования.

Проблема:

Вы сталкиваетесь с тем, что при попытке отправить несколько форм за раз с использованием подхода, который подразумевает полное перезагрузку страницы, предыдущие отправки прерываются. Это происходит потому, что после отправки первой формы страница перезагружается, и последующие вызовы не имеют возможности завершиться.

Решение:

Одним из решений этой проблемы является изменение вашего подхода к обработке отправки форм с использованием Promise и setTimeout для создания асинхронной задержки между отправками. Это позволит вам отправлять каждую форму последовательно, не загружая страницу заново, что обеспечит успешное выполнение каждого запроса.

Обновленный код:

Вот обновленный код, который использует async/await и Promise для отправки форм:

document.getElementById('saveAll').addEventListener('click', async () => {
    const addText = document.getElementById('add2BoxText').value;

    chrome.tabs.query({ active: true, currentWindow: true }, (tabs) => {
        chrome.scripting.executeScript({
            target: { tabId: tabs[0].id },
            function: saveAllBoxes
        });
    });
});

async function saveAllBoxes() {
    const theForm = document.forms['aspnetForm'];
    const all_td_a = document.querySelectorAll('td a');

    for (const element of all_td_a) {
        if (element.text === 'Spara') {
            element.text = "Saved";
            const fullLink = getEventTarget(element.href);
            await __doPostBack(fullLink, '');
        }
    }
}

function getEventTarget(href) {
    return href.substring(href.indexOf("'") + 1, href.lastIndexOf("'") - 3);
}

async function __doPostBack(eventTarget, eventArgument) {
    const formClone = document.forms['aspnetForm'].cloneNode(true);
    const iframe = document.createElement('iframe');

    iframe.style.display = 'none';
    document.body.appendChild(iframe);
    iframe.contentDocument.body.appendChild(formClone);

    return new Promise((resolve) => {
        formClone.__EVENTTARGET.value = eventTarget;
        formClone.__EVENTARGUMENT.value = eventArgument;

        formClone.onsubmit = function () {
            setTimeout(() => {
                document.body.removeChild(iframe);
                resolve();
            }, 2500); // Задержка 2.5 секунд, чтобы дождаться обработки на сервере
            return true; // Позволяем отправку формы
        };

        formClone.submit();
    });
}

Объяснение кода:

  1. Асинхронная функция: Мы объявляем функцию saveAllBoxes как асинхронную, что позволяет нам использовать await для ожидания выполнения каждого запроса.

  2. Создание Promise: Функция __doPostBack возвращает Promise. Это позволяет кодовой базе ожидать завершения отправки формы перед запуском следующей отправки.

  3. Задержка: Используя setTimeout, мы добавляем задержку, чтобы убедиться, что сервер успевает обработать запрос, прежде чем мы продолжим с отправкой следующей формы. Задержка в 2500 мс (2,5 секунды) является произвольным значением и может быть изменена в зависимости от производительности вашего сервера.

Заключение:

Применив предложенные изменения, вы сможете успешно отправить все формы на странице без перезагрузки, гарантируя, что каждая оценка будет обновлена с актуальной отметкой времени. Убедитесь, что сервер может обрабатывать каждую отправку корректно, чтобы избежать возможных задержек или ошибок.

Оцените материал
Добавить комментарий

Капча загружается...