Подробно о цикле событий в JavaScript
JavaScript — пожалуй, самый неоднозначный язык программирования в мире веб-разработки. Часто его хвалят за гибкость и универсальность, но при этом ругают за странные особенности поведения и непредсказуемость. Однако за многими "странностями" JavaScript скрывается ключевой механизм, который и делает этот язык таким мощным — цикл событий (Event Loop). Цикл событий — это основа асинхронности JavaScript, тот скрытый от глаз механизм, благодаря которому однопоточный язык способен обрабатывать множество операций практически одновременно. Вопреки распространённому заблуждению, JavaScript не имеет встроенной многопоточности, как другие языки программирования. Вместо этого он использует уникальную архитектуру, которая позволяет ему выполнять операции ввода-вывода без блокировки основного потока. Влияние цикла событий на архитектуру современных веб-приложенийСовременные веб-приложения часто содержат сложную логику: запросы к серверу, анимации, обработку пользовательских действий. Без цикла событий разработчикам пришлось бы вручную управлять выполнением операций, что приводило бы к "замороженному" интерфейсу при каждом запросе данных. Возьмём для примера Trello — популярный инструмент для управления проектами. Когда пользователь перемещает карточку между колонками, интерфейс остаётся отзывчивым, даже когда в фоне происходит сохранение изменений на сервере. Это возможно именно благодаря циклу событый, который позволяет отделить пользовательский интерфейс от процессов обработки данных. Фреймворки вроде React, Angular и Vue еще больше усложнили архитектуру приложений, добавив свои уровни абстракции. Но под капотом они все равно полагаються на цикл событий для обеспечения плавной работы и отзывчивого взаимодействия с пользователем. Написать программу для добавления обработчика событий HTML-элемента с возможностью использования делегирования событий. Назачение обработчиков событий в цикле. Установка событий в цикле (установка change на select при обходе массива DIV) Тема: Программирование на JavaScript. Обработка событий Основы асинхронной природы JavaScriptJavaScript изначально создавался как язык сценариев для веб-страниц, но мало кто предполагал, что он превратится в основу для сложных веб-приложений, серверных систем и даже мобильных платформ. Эта универсальность во многом стала возможна благодаря асинхронной природе JavaScript, которая часто вызывает недоумение у разработчиков, привыкших к синхронным языкам программирования. Однопоточность JavaScript: и ограничение, и силаКлючевая особенность JavaScript — его однопоточность. Это означает, что в любой момент времени выполняется только одна операция. Когда вы пишете код вроде:
При этом у разработчика может возникнуть вопрос: если JavaScript однопоточный, как же он справляется с длительными операциями? Например, загрузка файла с сервера может занять несколько секунд. Неужели в это время весь пользовательский интерфейс "замерзает"? Неблокирующий ввод-вывод и цикл событийСекрет заключается в том, что JavaScript использует неблокирующую модель для операций ввода-вывода. Когда выполняется асинхронная операция (например, fetch для загрузки данных с сервера), JavaScript не ждёт её завершения, а продолжает выполнять другой код. Когда операция завершается, соответствующая функция колбэка добавляется в очередь задач для последующего выполнения. И именно здесь выходит цикл событий. Он постоянно проверяет стек вызовов и, если он пуст, берет первую задачу из очереди и помещает её в стек для выполнения. Давайте рассмотрим простой пример:
Когда встречается setTimeout , браузер запускает таймер, а сам JavaScript продолжает выполнение. Через секунду браузер добавляет колбэк в очередь задач, и когда стек вызовов освобождается, цикл событий вытаскивает этот колбэк из очереди и выполняет его.Модель конкурентного выполнения: иллюзия многозадачностиJavaScript создаёт иллюзию многозадачности через модель конкурентного выполнения. Хотя в каждый момент времени выполняется только одна операция, частое переключение между разными задачами создаёт впечатление параллельной работы. Представьте жонглёра с несколькими мячиками. В каждый конкретный момент он держит только один мячик, но быстро переключаясь между ними, создаёт иллюзию, что все мячики находятся в воздухе одновременно. Таким же образом JavaScript жонглирует задачами, создавая иллюзию параллельного выполнения. Эта модель отлично подходит для веб-приложений, где большую часть времени программа ожидает действий пользователя или загрузки данных. В промежутках между этими событиями JavaScript может выполнять другие задачи, поддерживая отзывчивость интерфейса. Однако у этой модели есть и очевидные недостатки. Если одна из задач требует интенсивных вычислений и занимает слишком много времени, все остальные задачи будут ждать, что может привести к "зависанию" интерфейса. Рассмотрим пример кода, который демонстрирует проблему блокировки:
блокирующаяОперация захватывает поток выполнения на 3 секунды, и за это время никакой другой код не может выполняться. Кнопки на странице не будут реагировать, анимации остановятся, и пользователь увидит "зависшую" страницу.Пример из реальной практики: отзывчивый интерфейсЧтобы лучше понять важность асинхронного программирования, расмотрим практическую задачу: поиск в базе данных из миллиона записей. В синхронном коде это могло бы выглядеть так:
setTimeout с нулевой задержкой используется для того, чтобы отложить выполнение поиска до следующей итерации цикла событий. В результате интерфейс остаётся отзывчивым, и пользователь может продолжать взаимодействие с страницей.Современный JavaScript предлагает более элегантные способы работы с асинхронным кодом, такие как промисы и async/await, но цикл событий по-прежнему остаётся фундаментом, на котором строится асинхронность в языке. В JavaScript разработчики сталкиваются с множеством паттернов для работы с асинхронным кодом. Эволюция этих паттернов демонстрирует, как язык постепенно адаптировался к растущей сложности веб-приложений. Эволюция асинхронных паттернов: от колбэков до async/awaitПервым и самым примитивным паттерном были колбэки — функции, которые передаются в качестве аргументов и вызываются по завершении асинхронной операции. Проблема колбэков проявляется при вложенности, создавая печально известный "колбэк-ад":
async всегда возвращает промис, а await приостанавливает выполнение только внутри этой функции, не блокируя основной поток.Асинхронность vs параллелизмВажно понимать разницу между асинхронностью и параллелизмом. Асинхронность в JavaScript — это модель выполнения, при которой операции запускаются и завершаются в перекрывающиеся промежутки времени. Но они всё равно выполняются в одном потоке, просто не обязательно сразу и по порядку. Параллелизм подразумевает одновременное выполнение нескольких операций на разных ядрах процессора. JavaScript в браузере и Node.js сам по себе не предоставляет настоящего параллелизма, но современные платформы предлагают Web Workers — способ создать отдельные потоки для выполнения JavaScript-кода.
Цикл событий и рендеринг страницыОсобо следует отметить, как цикл событий взаимодействует с процессом рендеринга в браузере. Между итерациями цикла событий браузер может обновлять отображение страницы, но длительные операции в JavaScript могут откладывать эти обновления, что приводит к "дёрганному" интерфейсу. Чтобы обеспечить плавную анимацию и отзывчивый интерфейс, критически важно не блокировать основной поток надолго. Исследователи определили, что для обеспечения плавности интерфейса каждый фрейм должен обрабатываться не дольше 16 миллисекунд (чтобы достичь 60 кадров в секунду). Один из подходов к оптимизации — разбиение длительных задач на серию более коротких операций, которые не блокируют цикл событий надолго:
Итак, мы рассмотрели расширенные аспекты асинхронного программирования в JavaScript, эволюцию паттернов от колбэков до async/await, разницу между асинхронностью и параллелизмом, и как правильно работать с циклом событий, чтобы обеспечить плавный пользовательский интерфейс. В следующем разделе мы более глубоко изучим внутреннее устройство цикла событий, чтобы понять, как он координирует выполнение всех этих различных типов задач. Анатомия цикла событийЧтобы действительно понять, как работает JavaScript, нужно заглянуть под капот цикла событий и разобраться с его составными частями. Компоненты цикла событий: взгляд изнутриЦиклом событий управляет несколько ключевых компонентов, которые образуют систему координации выполнения кода: 1. Стек вызовов (Call Stack) — своеобразный журнал того, где сейчас находится интерпретатор JavaScript. Представьте его как стопку книг: новые вызовы функций кладутся сверху стопки, а когда функция завершается, она "снимается" с верха стека. 2. Очередь задач (Task Queue) — очередь событий, которые должны быть обработаны. Сюда попадают макрозадачи: таймеры, события ввода-вывода, пользовательские события и т.д. 3. Очередь микрозадач (Microtask Queue) — очередь с более высоким приоритетом, чем обычная очередь задач. Сюда входят задачи, создаваемые промисами и MutationObserver. 4. Web APIs (в браузере) или C++ APIs (в Node.js) — именно здесь "живут" асинхронные операции во время ожидания. JavaScript делегирует асинхронные операции этим API и продолжает выполнение кода. Взаимодействие между этими компонентами формирует основу асинхронной модели JavaScript. Понимание этого взаимодействия даёт ключ к написанию эффективного и предсказуемого кода. Алгоритм работы цикла событийЦикл событий работает по следующему алгоритму: 1. Проверить стек вызовов. Если он не пуст, продолжаем выполнять текущий код. 2. Если стек пуст, проверить очередь микрозадач. Если там есть задачи, выполнить их все до единой. 3. Если очередь микрозадач пуста, проверить очередь задач. Если там есть задача, взять первую и передать её в стек вызовов. 4. Повторить процесс. Между выполнением задач может быть выполнен рендеринг страницы, если это необходимо. Это обеспечивает отзывчивость интерфейса даже при интенсивной работе JavaScript. Вот визуальное представление цикла событий (объясняем схему словами): 1. Синхронный код выполняется и помещается в стек вызовов. 2. Асинхронные операции передаются Web APIs. 3. Когда асинхронная операция завершается, соответствующий коллбэк перемещается в очередь задач или микрозадач. 4. Когда стек вызовов пуст, цикл событий берет задачи из очередей для выполнения. Важно: очередь микрозадач всегда опустошается полностью перед тем, как цикл событий перейдет к следующей задаче из основной очереди. Это объясняет, почему промисы выполняются до setTimeout, даже если setTimeout с нулевой задержкой. Пример разбора выполнения кодаРазберем конкретный пример, чтобы увидеть, как работает цикл событий:
1. "Скрипт начался" и "Скрипт закончился" выполняются синхронно, прямо в стеке вызовов. 2. setTimeout передаётся браузерным API, которые запускают таймер (даже при нулевой задержке).3. Промисы добавляют свои функции-обработчики в очередь микрозадач. 4. Когда синхронный код выполнен, цикл событий опустошает очередь микрозадач, выполняя все обработчики промисов. 5. Только после этого он переходит к выполнению задач из очереди задач, где лежат колбэки таймеров. Особенности реализации цикла событий в разных средахИнтересно, что цикл событий реализован по-разному в браузерах и Node.js. В браузере цикл событий является частью среды выполнения JavaScript, в то время как в Node.js он реализован на базе библиотеки libuv. В Node.js очередь задач разделена на несколько фаз, включая:
Эта разница в реализации приводит к некоторым тонким отличиям в поведении асинхронного кода. Например, в Node.js setImmediate может выполниться до setTimeout(callback, 0) в некоторых случаях, в то время как в браузере такого API даже не существует.Рендеринг и цикл событийСтоит отметить, что рендеринг страницы в браузере также координируется циклом событий. В идеальном сценарии, браузер пытается обновлять изображение на экране примерно 60 раз в секунду (60 FPS), что означает, что у каждого фрейма есть около 16.7 миллисекунд на обработку. Обновление экрана происходит между итерациями цикла событий. Если задача в JavaScript выполняеться дольше чем 16.7 мс, это приводит к пропуску кадров и "подтормаживанию" анимации. Вот почему так важно разбивать тяжёлые вычисления на более мелкие части и использовать такие API как requestAnimationFrame для синхронизации с циклом обновления экрана.Макрозадачи и микрозадачи: приоритеты выполненияВозможно, самый запутанный аспект цикла событий — это взаимоотношения между макрозадачами и микрозадачами. Не все асинхронные операции созданы равными. Они имеют разный приоритет, что напрямую влияет на порядок их выполнения. Макрозадачи (Task Queue) включают:
Микрозадачи (Microtask Queue) включают:
Ключевое отличие в том, что цикл событий полностью опустошает очередь микрозадач перед тем, как взять следующую макрозадачу. Более того, если во время выполнения микрозадачи в очередь добавляються новые микрозадачи, они также будут выполнены до перехода к следующей макрозадаче. Вот показательный пример:
1. Синхронный код всегда выполняется первым. 2. Все микрозадачи из текущей очереди выполняются до перехода к следующей макрозадаче. 3. Микрозадачи, созданные во время выполнения других микрозадач или макрозадач, попадают в текущую очередь микрозадач. 4. Новые макрозадачи всегда ставятся в конец своей очереди. Тонкости управления очередностью задачПонимание приоритетов макро- и микрозадач даёт мощный инструмент для управления порядком выполнения кода. Вот несколько практических применений: 1. Гарантированное выполнение после рендеринга — используйте макрозадачи (`setTimeout(fn, 0)`) когда нужно, чтобы функция выполнилась после обновления DOM и перерисовки страницы. 2. Выполнение до следующего кадра рендеринга — используйте микрозадачи ( queueMicrotask() ) когда нужно выполнить код до следующего рендеринга, но после текущего синхронного кода.3. Синхронизация с циклом анимации — для плавных анимаций используйте requestAnimationFrame() , который запускается перед перерисовкой экрана, но после выполнения микрозадач.Давайте рассмотрим пример, демонстрирующий точное управление потоком выполнения с использованием разных очередей:
requestAnimationFrame выполняетя в особый момент цикла — перед рендерингом, но после всех микрозадач и до следующей макрозадачи. Это делает его идеальным инструментом для анимаций.Отладка и инструменты для работы с циклом событийВизуализация и отладка цикла событий — важный навык для JavaScript-разработчика. Современные браузеры предоставляют мощные инструменты для этого: 1. Performance Tab в Chrome DevTools — позволяет записать и проанализировать выполнение JavaScript, увидеть, как распределены задачи и определить причины задержек в интерфейсе. 2. Async Stack Traces — большинство современных браузеров поддерживают просмотр асинхронного стека вызовов, что помогает понять, откуда пришла асинхронная задача. 3. Инструменты для Node.js — в серверном JavaScript можно использовать модули вроде async_hooks для отслеживания асинхронных ресурсов и их жизненного цикла.Одна из моих любимых методик отладки — добавление временных меток с помощью console.time() и console.timeEnd() для измерения времени выполнения задач:
Практические примеры с кодомВ этом разделе мы разберем реальные примеры, которые демонстрируют работу цикла событий в боевых условиях и научимся использовать его особенности для создания эффективного кода. Таймеры и их непредсказуемостьНачнём с одного из самых распространённых источников путаницы — таймеров. Многие разработчики ошибочно полагают, что setTimeout(callback, 1000) гарантированно вызовет функцию ровно через 1000 миллисекунд. На самом деле, это не совсем так.
setTimeout , могут "подтормаживать" при интенсивных вычислениях — цикл событий не может вовремя вытащить колбэк таймера из очереди задач.Дебаунс и тротлинг: укрощение событийОдна из частых задач — обработка серии быстрых событий, например, событий прокрутки или изменения размера окна. Здесь на помощь приходят паттерны дебаунсинга и тротлинга, реализация которых напрямую связана с циклом событий. Вот пример функции дебаунсинга:
А вот пример функции тротлинга, которая обеспечивает выполнение функции не чаще заданного интервала:
Промисы и микрозадачи в действииПромисы кардинально изменили подход к асинхронному программированию в JavaScript. Вспомним, что обработчики .then() , .catch() и .finally() попадают в очередь микрозадач, а не макрозадач. Это создает интересные паттерны взаимодействия.
Async/await и потоки выполненияСинтаксис async/await, появившийся в ES2017, построен на промисах, но создаёт иллюзию синхронного выполнения. Однако под капотом это всё те же асинхронные операции:
await "приостанавливает" выполнение асинхронной функции, но не останавливает выполнение JavaScript. Цикл событий продолжает работу, выполняя код после вызова функции, а затем возвращается к приостановленной функции, когда промис разрешается.Создание анимаций с requestAnimationFrameДля создания плавных анимаций в браузере лучше использовать специальный API — requestAnimationFrame , который синхронизируется с циклом обновления экрана:
setTimeout , requestAnimationFrame вызывается браузером именно перед обновлением экрана, что обеспечивает плавную анимацию без лишних перерисовок.Создание отзывчивого интерфейса при тяжёлых вычисленияхРеальный кейс: представьте, что вам нужно обработать большой массив данных (например, отсортировать 100,000 элементов) в браузере. Наивная реализация заблокирует интерфейс:
Web Workers: настоящий параллелизм для тяжёлых задачКогда даже разбиение на порции не помогает из-за сложности вычислений, на помощь приходят Web Workers — способ выполнять JavaScript в отдельных потоках.
Fetch API и прерывание запросовСовременная сетевая работа в JavaScript часто выполняеся через Fetch API, который также взаимодействует с циклом событий. Важная возможность — прерывание запросов, если пользователь не хочет ждать завершения:
Очередь событий и их приоритизацияИногда необходимо тонко управлять порядком выполнения асинхронных операций. JavaScript предоставляет различные механизмы для этого:
Оптимизация производительностиПонимание цикла событий даёт мощный инструментарий не только для написания корректного кода, но и для его оптимизации. JavaScript может быть либо молниеносно быстрым, либо угнетающе медленным — всё зависит от того, как именно мы используем цикл событий. Рассмотрим основные приёмы повышения производительности и распространённые ошибки, которые тормозят наши приложения. Тяжёлые вычисления и блокировка потокаСамая распространённая причина "фризов" интерфейса — длительные синхронные операции, которые блокируют основной поток. Напомню, что JavaScript однопоточный, и пока выполняется синхронный код, никакие другие операции выполняться не могут, включая отрисовку изменений пользовательского интерфейса. Вот наглядный пример кода, который гарантированно подвесит браузер:
Неэффективные обработчики событийЕщё одна распространенная ошибка — навешивание "тяжёлых" обработчиков на частые события, такие как scroll , resize или mousemove . Каждое такое событие создаёт задачу в очереди макрозадач, и если обработка каждого события занимает много времени, очередь быстро переполняется.Решение — использовать техники дебаунсинга и тротлинга:
Необоснованное использование микрозадачХотя микрозадачи имеют высокий приоритет, их чрезмерное использование может приводить к проблемам. Помните, что цикл событий полностью опустошает очередь микрозадач перед переходом к следующей макрозадаче. Если каждая микрозадача порождает новые микрозадачи, цикл может "зациклиться" в очереди микрозадач, никогда не добираясь до обработки пользовательского ввода или отрисовки.
Оптимизация критического пути рендерингаДля веб-приложений критически важно оптимизировать работу JavaScript с учётом процесса рендеринга страницы. Вот несколько полезных приёмов: 1. Используйте requestAnimationFrame для анимаций вместо setTimeout — это синхронизирует ваш код с циклом перерисовки браузера.2. Избегайте преждевременных оптимизаций — сначала измерьте производительность с помощью инструментов профилирования, затем оптимизируйте узкие места. 3. Минимизируйте перерасчёт стилей и компоновки — групируйте изменения DOM и стилей, используйте CSS-классы вместо инлайновых стилей. 4. Используйте виртуализацию для больших списков — отрисовывайте только видимые элементы, это особенно важно для мобильных устройств. Мониторинг производительности цикла событийДля диагностики проблем с производительностью, связанных с циклом событий, есть ряд полезных техник:
PerformanceObserver позволяет отслеживать "длинные задачи" — операции, которые блокируют основной поток более чем на 50мс, потенциально влияя на отзывчивость интерфейса.Также можно использовать метрику First Input Delay (FID) для оценки отзывчивости страницы:
Сравнение с другими языкамиАсинхронность в программировании — не уникальная особенность JavaScript. Множество других языков имеют собственные механизмы для обработки асинхронных операций, но подходы заметно различаются. Изучение этих различий помогает глубже понять уникальность цикла событий JavaScript и его влияние на архитектуру веб-приложений. Классические многопоточные языки: Java и C++В отличие от однопоточного JavaScript, языки вроде Java и C++ изначально проектировались с учётом многопоточности. Разработчик на этих языках создаёт и управляет потоками явно:
Python и асинхронное программирование через asyncioС версии 3.4 Python предлагает библиотеку asyncio, которая во многом вдохновлена моделью цикла событий JavaScript:
C# и Task Parallel LibraryC# предлагает развитую систему для асинхронного программирования через TPL (Task Parallel Library):
Rust и futuresRust предлагает низкоуровневый контроль над асинхронными операциями через концепцию "futures" (будущие значения):
Сравнение с моделями событий в React, Angular и VueХотя JavaScript-фреймворки работают на основе всё того же цикла событий, они добавляют свои уровни абстракции: React с его односторонним потоком данных и виртуальным DOM вводит понятие "синтетических событий", которые нормализуют браузерные события. React использует "fiber" архитектуру, которая позволяет прерывать и возобновлять рендеринг компонентов, разбивая работу на куски — это своеобразная реализация принципов time slicing в рамках цикла событий JavaScript. Angular использует RxJS и его Observable, которые являются мощным инструментом для работы с асинхронными потоками данных. Angular Zone.js перехватывает все асинхронные операции, что позволяет фреймворку автоматически обнаруживать изменения данных и обновлять UI, не требуя ручного вызова обновлений. Vue применяет реактивную модель данных, где изменения автоматически распространяются на зависящие части приложения. Vue's Composition API, появившийся с версии 3, предоставляет более функциональный подход к управлению реактивностью, напоминая подход React с хуками, но с отличиями в реализации. В отличие от низкоуровневого JavaScript, эти фреймворки предлагают более структурированные и декларативные способы работы с асинхронными операциями и событиями пользовательского интерфейса, но в основе всего по-прежнему лежит цикл событий JavaScript, определяющий фундаментальные ограничения и возможности веб-платформы. Подводя итоги: значение цикла событий в JavaScriptПонимание цикла событий – ключ к овладению JavaScript на профессиональном уровне. Разработчик, просто использующий асинхронные функции, подобен водителю, который умеет ездить, не понимая, как работает двигатель. В штатных ситуациях всё идёт гладко, но при возникновении проблем он оказывается беспомощен. Цикл событий затрагивает практически все аспекты JavaScript-разработки: от обработки пользовательского ввода до оптимизации тяжёлых вычислений. Знание его механизмов помогает создавать отзывчивые интерфейсы, избегать "подвисаний" страницы и предугадывать нетривиальные взаимодействия между асинхронными операциями. Каждый раз, когда мы используем setTimeout , обещания или async/await , мы взаимодействуем с циклом событий. Когда мы отлаживаем странное поведение асинхронного кода или оптимизируем производительность, именно понимание цикла событий часто даёт ответы на самые сложные вопросы.Надеюсь, эта статья помогла вам заглянуть за кулисы JavaScript и увидеть, как асинхронная магия превращается в чёткую, предсказуемую систему. Вооружившись этим знанием, вы сможете писать более элегантный, эффективный и надёжный код. JavaScript обработчики событий JavaScript + обработка событий JavaScript + обработка событий Разработка JavaScript-программы для обработки событий в различных фреймах Разработка JavaScript-программы для обработки событий в различных фреймах Обработка событий на JavaScript Объясните подробно как создать свой форум с нуля? Объясните пожалуйста подробно код js Обясните подробно что ето где подробно описан объект Event? Подробно объяснить AJAX-функции скрипта для постинга комментариев Подробно разбираем задачу Обхода по дереву с применением reduce |
-
Ну нельзя просто так сортировать массивы по частям. Если отдельно отсортировать одну половину, вторую половину, то массив не будет отсортирован целиком. Потом же все равно придется делать сортировку (например, слиянием).
JavaScript 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50
function обработатьДанныеПоЧастям(данные, колбэкПрогресса, колбэкЗавершения) { console.log('Начинаем обработку'); const всегоЭлементов = данные.length; let обработано = 0; const размерПорции = 10000; const результат = []; function обработатьПорцию() { // Берём следующую порцию данных const конец = Math.min(обработано + размерПорции, всегоЭлементов); const порция = данные.slice(обработано, конец); // Обрабатываем порцию const частичныйРезультат = порция .sort((a, b) => a - b) .filter(x => x > 0) .map(x => x * 2); результат.push(...частичныйРезультат); обработано = конец; // Сообщаем о прогрессе колбэкПрогресса(Math.floor((обработано / всегоЭлементов) * 100)); // Если ещё не всё обработано, планируем следующую порцию if (обработано < всегоЭлементов) { setTimeout(обработатьПорцию, 0); } else { console.log('Обработка завершена'); колбэкЗавершения(результат); } } // Запускаем обработку первой порции setTimeout(обработатьПорцию, 0); } // Использование обработатьДанныеПоЧастям( огромныйМассив, (процент) => { console.log(`Прогресс: ${процент}%`); // Обновить индикатор прогресса в UI }, (результат) => { console.log(`Получен результат с ${результат.length} элементами`); // Отобразить результат в UI } );
Ну перестаньте вы писать чушь. Или хотя бы сами проверяйте свои примеры перед тем, как их выложить.Запись от voraa размещена 07.05.2025 в 19:06