Вопрос или проблема
У нас в школе есть старая образовательная платформа с низкой удобочитаемостью. Я стараюсь улучшить её, написав дополнение для себя и своих коллег. Мне удалось сделать несколько вещей, но я застрял, пытаясь отправить несколько форм одновременно. Задача следующая: на веб-странице есть список всех моих студентов. Для каждого из них предусмотрено текстовое поле для оценивания и ссылка “Сохранить”, которая обновляет и устанавливает текущее время и дату в качестве временной метки для текста.
Ссылка вызывает метод, который копирует некоторые параметры в форму и отправляет её. Это известно как механизм постбека 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();
});
}
Объяснение кода:
-
Асинхронная функция: Мы объявляем функцию
saveAllBoxes
как асинхронную, что позволяет нам использоватьawait
для ожидания выполнения каждого запроса. -
Создание
Promise
: Функция__doPostBack
возвращаетPromise
. Это позволяет кодовой базе ожидать завершения отправки формы перед запуском следующей отправки. -
Задержка: Используя
setTimeout
, мы добавляем задержку, чтобы убедиться, что сервер успевает обработать запрос, прежде чем мы продолжим с отправкой следующей формы. Задержка в 2500 мс (2,5 секунды) является произвольным значением и может быть изменена в зависимости от производительности вашего сервера.
Заключение:
Применив предложенные изменения, вы сможете успешно отправить все формы на странице без перезагрузки, гарантируя, что каждая оценка будет обновлена с актуальной отметкой времени. Убедитесь, что сервер может обрабатывать каждую отправку корректно, чтобы избежать возможных задержек или ошибок.