Задать вопрос
@hippocrates_ho_koios
врач-кибернетик

Как избежать зависание textarea при обработке большого массива?

Добрый день. На поле textarea висит обработчик события 'input', который запускает обработку большого массива в цикле, из-за чего после ввода текста textarea "зависает" и дальнейший ввод становится на пару секунд невозможным. Как обернуть этот процесс в асинхронную функцию?

UPD: таки реализовал с помощью веб-воркеров. Или есть лучший вариант?
  • Вопрос задан
  • 287 просмотров
Подписаться 3 Простой Комментировать
Решения вопроса 1
@historydev Куратор тега JavaScript
Редактирую файлы с непонятными расширениями
<input type="text" id="textarea">

// Код воркера в виде строки
const workerCode = `
  self.onmessage = (event) => {
    const largeArray = event.data;
    
    // Выполнение тяжелой обработки массива
    for (let i = 0; i < largeArray.length; i++) {
      // Например: largeArray[i] = someProcessing(largeArray[i]);
      largeArray[i] *= 2; // Пример обработки: удваиваем каждый элемент
    }

    // Отправка обработанных данных обратно в главный поток
    self.postMessage(largeArray);
  };
`;

// Создание Blob из строки с кодом воркера
const blob = new Blob([workerCode], { type: 'application/javascript' });
// Создание объекта Worker из URL на Blob
const worker = new Worker(URL.createObjectURL(blob));

// Обработка сообщений от воркера
worker.onmessage = (event) => {
  const processedArray = event.data;
  console.log('Обработанный массив:', processedArray);
  // Можно обновить интерфейс или использовать данные
};

// Пример массива для обработки
const largeArray = new Array(1e6).fill(15);

function debounce(func, delay) {
  let timeout;
  return function(...args) {
      clearTimeout(timeout);
      timeout = setTimeout(() => func.apply(this, args), delay);
  };
}

const handleInput = debounce(() => {
  worker.postMessage(largeArray);
}, 300); // Вызываем через 300 мс после окончания ввода

// Пример добавления обработчика для textarea
textarea.addEventListener('input', (event) => {
  console.log(event.target.value);
  handleInput();
});
Ответ написан
Пригласить эксперта
Ответы на вопрос 2
@iljaGolubev
Debounce

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

пример для илюстрации
const debounce = (callback, wait) => {
  let timeoutId = null;
  return (...args) => {
    window.clearTimeout(timeoutId); // повторый вызов отменит предыдущий
    timeoutId = window.setTimeout(() => {
      callback(...args);
    }, wait); // и запустит новый
  };
}

const runDebouncedBigArrayOnInputEnds = debounce(
    (event) => {
      // запускает обработку большого массива в цикле
    }, 
   250 // сколько ждать завершения ввода
);

document.getElementById('#myTxtField').addEventListener('input', runDebouncedBigArrayOnInputEnds );
Ответ написан
zkrvndm
@zkrvndm
Архитектор решений
Вы можете использовать нативный Scheduler API для выполнения тяжёлого цикла с пониженным приоритетом и это не будет блокировать интерфейс.

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


https://developer.mozilla.org/en-US/docs/Web/API/S...
Ответ написан
Комментировать
Ваш ответ на вопрос

Войдите, чтобы написать ответ

Похожие вопросы