Проблема с setTimeout [страница перезагружается при отправке формы, но не должна]

есть простая страница, которая на вход принимает *.csv и выдаёт *.pdf. сначала есть только кнопка загрузить файл, после загрузки-обработки появляется кнопка скачать пдф, которая запускает библиотеку makePdf и отдаёт готовый файл.
если на вход подаётся небольшой файл, то проблем нет. при увеличении размера страница выглядит подвисшей, даже алерт появляется. поэтому была добавлена промежуточная функция

function runBuildPDF() {
  spinner.classList.add('spinner_shown');
  button.classList.remove('download_shown');
  setTimeout(() => {
    buildPdf()
  }, 10);
}

что привело к необъяснимому поведению: первый запуск всегда приводит к рестарту страницы. то есть нажимаем загрузить csv, далее загрузить пдф и страница тут же возвращается в исходное положение. даже если поставить большой таймаут - он просто игнорится. все последующие разы всё работает как и ожидается.

Создание pdf из cvs происходит на сервере или на самой странице? Создание pdf происходит синхронно относительно запроса на сервер (иными словами известно ли что файл создан погда браузер получает ответ тот сервера)?

Нужно больше кода из реализации чтобы понять что происходит (в идеале вся страница, не в идеале содержимое buildPdf потом что она ответственна за “зависание” страницы с которого все и началось). Есть подозрение что код местами реализован синхронно (смысле сихронный запрос на сервер) там где нужно бы реализовать асинхронно. Есть подозрение что если генерация pdf происходит на клиенте, то на время пока pdf генерируется UI блокируется (чтобы этого не было надо вынести генерацию в web-worker или “поиграться” с доступным API).

1 лайк

Была предпринята попытка минималистичной страницы. в index.html подключен pdfMake:
<скрипт src=“https://cdnjs.cloudflare.com/ajax/libs/pdfmake/0.2.10/pdfmake.min.js” type=“text/javascript”></скрипт>
Если правильно понимаю, то вся генерация происходит локально.
Логика такова:

  • есть функция, которая срабатывает при изменении формы (onchange=“proceedUploadedFile(event)”) и помещает содержимое csv в array. Если файл был корректно прочитан, то прячется кнопка загрузки и появляется кнопка для скачивания пдф.

  • на кнопку скачивания/ на сабмит формы (пробовал и так и так - результат тот же) привязана функция runBuildPDF(). Её основная функция дать понять, что страница не висит, а идёт какая-то внутренняя работа и вызвать после паузы функцию генерации пдф.
    function buildPdf() {
    const tableReady = ;

    for (let i = 0; i < proceededData.length; i = i + 3) {
    подготовка данных макета: tableReady
    }

    const pdfData = {
    создание макета
    };

    spinner.classList.remove(‘spinner_shown’);
    button.classList.add(‘download_shown’);

    pdfMake.createPdf(pdfData).download(pdfName);

    setTimeout(() => {
    tableReady.length = 0;
    }, 1)
    };

Хотел бы сакцентировать внимание, что setTimeout используется как пауза, которая нужна для изменения классов кнопки и спинера. И проблема с рестартом страницы проявляется только (!!!) при 1ом запуске страницы, все последующие разы проблемы нет.

Сфокусируемся пока только на этом аспекте.

Думаю что это поведение из-за того что срабатывает стандартный обработчик событий сабмита формы (что в свою очередь приводит к перезагрузке страницы). В коде надо отменить событие отправки формы (внимание, это не тоже самое что и событие клика на кнопку отправки формы).

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

FORM_DOM_NODE.addEventListener("submit", (event) => {
event.preventDefault();
// buildPdf() ...
});
1 лайк

Добавил listener:
form.addEventListener(‘submit’, (event) => {
event.preventDefault();
spinner.classList.add(‘spinner_shown’);
button.classList.remove(‘download_shown’);
setTimeout(() => {
buildPdf();
}, 10)
})

Работает, перезапуска страницы нет. Теперь пазл сложился. Спасибо огромное!

1 лайк