Автор оригинала: FreeCodeCamp Community Member.
Голодный мозг
JavaScript – это отдельные резьбовые, а несколько скриптов не могут одновременно выполняться. Поэтому, если мы выполним любые тяжелые задачи вычислений, то иногда наша страница стала не отвечать, и пользователь не может сделать что-то еще, пока это выполнение не будет завершено.
Например:
average = (numbers) => { let startTime = new Date().getTime(); let len = numbers, sum = 0, i; if (len === 0) { return 0; } for (i = 0; i < len; i++) { console.log('i :: ', i) sum += i; } let endTime = new Date().getTime(); alert('Average - ', sum / len); } hello = () => { alert("Hello World !!"); } /* Paste the above code in browser dev tool console and try to call average(10000) and hello one by one */
В приведенном выше примере, если вы звоните средний до Привет Метод, то ваша страница станет не отвечает, и вы не сможете нажать на Привет до исполнения средний завершено.
Вы можете увидеть, что когда средний Сначала называется 10000 в качестве ввода, он занял ~ 1,82 секунды. Для этого времени страница становится не реагированной, и вы не смогли нажать на кнопку Hello.
Асинхронное программирование
JavaScript дает возможность разработчикам написать ASYNC код Отказ Начиняя асинхронный код, вы можете избежать такого типа в своем приложении, поскольку он позволяет отвечать вашему приложению UI, по «планированию» частей кода выполняются немного позже в контуре события.
Хороший пример Async Programming – XHR запрос
В этом мы ударили API асинхронно и в ожидании ответа, другой код может быть выполнен. Но это ограничено определенным случаям использования, связанные с Web API в основном.
Еще один способ написания Async Code использует Сетримс
метод. В некоторых случаях вы можете добиться хороших результатов в разблокировке UI от более длительных вычислений с помощью Сетримс
Отказ Например, путем насыщения сложного вычисления в отдельном Сетримс
звонки.
Например:
average = (numbers) => { let startTime = new Date().getTime(); var len = numbers, sum = 0, i; if (len === 0) { return 0; } let calculateSumAsync = (i) => { if (i < len) { // Put the next function call on the event loop. setTimeout(() => { sum += i; calculateSumAsync(i + 1); }, 0); } else { // The end of the array is reached so we're invoking the alert. let endTime = new Date().getTime(); alert('Average - ', sum / len); } }; calculateSumAsync(0); }; hello = () => { alert('Hello World !!') };
В этом примере вы можете увидеть, что после нажатия на Рассчитать среднее кнопка, вы все еще можете нажать на Привет Кнопка (которая в свою очередь показывает сообщение о предупреждении). Этот способ программирования, безусловно, не блокирует, но занимает слишком много времени, и не выполняется в реальном мире приложений.
Здесь, для того же входа 10000, он занял ~ 60 секунд, что очень неэффективно.
Итак, как мы решаем эти виды вопросов эффективно?
Ответ – Веб-работники.
Что такое веб-работники?
Web-работники в JavaScript – отличный способ выполнить некоторую задачу, которая очень трудонаправлена, и время, принимая в ните отдельно от основной нити. Они работают в фоновом режиме и выполняют задачи, не мешающие пользовательскому интерфейсу.
Интернет-рабочие не являются частью JavaScript, это функция браузера, которая может быть доступна через JavaScript.
Web-работники создаются функцией конструктора Работник () который запускает именованный файл JS.
// create a dedicated web worker const myWorker = new Worker('worker.js');
Если указанный файл существует, то он будет загружен асинхронно, и если нет, то работника не будет работать молча, поэтому ваше приложение будет работать в случае 404.
Мы узнаем больше о создании и работе веб-работников в следующем разделе.
Рабочий поток имеет свой собственный контекст и, следовательно, вы можете получить доступ к выбранным функциям внутри рабочей нити, как – веб-розетки, индексированные БД.
Есть некоторые Ограничения с веб-работниками –
- Вы не можете напрямую манипулировать домом изнутри рабочего.
- Вы не можете использовать некоторые методы по умолчанию и свойства объекта окна, поскольку Object Object недоступен внутри рабочей нити.
- Контекст внутри рабочей нити можно получить доступ через Выделенный рабочийЛобальсcope или SharedWorkergLobalscope в зависимости от использования.
Особенности веб-работников
Есть два типа веб-работников –
- Выделенный веб-работник – Выделенный работник доступен только скриптом, который назвал его.
- Общий веб-работник – Общий работник доступен несколькими сценариями – даже если они обращаются к разным окнам, IFRAMES или даже работникам.
Давайте обсудим больше о тех двух типах веб-работников –
Создание веб-работника
Создание в значительной степени же для преданного, так и для общего веб-работника.
Выделенный веб-работник
- Создание нового работника прост, просто позвоните рабочему конструктору и пропустите путь скрипта, который вы хотите выполнить в качестве работника.
// create a dedicated web worker const myWorker = new Worker('worker.js');
Общий веб-работник:
- Создание нового общего работника в значительной степени так же, как у специализированного работника, но с другим именем конструктора.
// creating a shared web worker const mySharedWorker = new SharedWorker('worker.js');
Связь между основной и рабочей нитью
Связь между основной нитью и рабочей нитью происходит через PostMessage Метод и OnMessage обработчик события.
Выделенный веб-работник В случае выделенного веб-работника система связи проста. Вам просто нужно использовать метод PostMessage, когда вы хотите отправить сообщение рабочему.
(() => { // new worker let myWorker = new Worker('worker.js'); // event handler to recieve message from worker myWorker.onmessage = (e) => { document.getElementById('time').innerHTML = `${e.data.time} seconds`; }; let average = (numbers) => { // sending message to web worker with an argument myWorker.postMessage(numbers); } average(1000); })();
А внутри веб-работника вы можете ответить, когда сообщение получено путем записи блока обработчика событий, как это:
onmessage = (e) => { let numbers = e.data; let startTime = new Date().getTime(); let len = numbers, sum = 0, i; if (len === 0) { return 0; } for (i = 0; i < len; i++) { sum += i; } let endTime = new Date().getTime(); postMessage({average: sum / len, time: ((endTime - startTime) / 1000)}) };
OnMessage
Обработчик позволяет запустить какойкий раз, когда сообщение получено сообщение.
Здесь мы рассчитываем средние числа, а затем используйте PostMessage ()
Опять же, чтобы опубликовать результат обратно в основную нить.
Как вы можете видеть на Линия 6 в main.js Мы использовали событие OnMessage на экземпляре работника. Так что всякий раз, когда рабочие потоки используют PostMessage, OnMessage в основном потоке запущено.
- Общий веб-работник В случае общего веб-работника система связи немного отличается. В качестве одного работника разделяется между несколькими сценариями, нам нужно общаться через объект портов работника. Это делается неявно в случае преданных работников. Вам необходимо использовать метод PostMessage, когда вы хотите отправить сообщение рабочему.
(() => { // new worker let myWorker = new Worker('worker.js'); // event handler to recieve message from worker myWorker.onmessage = (e) => { document.getElementById('time').innerHTML = `${e.data.time} seconds`; }; let average = (numbers) => { // sending message to web worker with an argument myWorker.postMessage(numbers); } average(1000);
Внутри веб-работника ( Main-Shared-Working.js ) Это немного сложна. Во-первых, мы используем Onconnect
Обработчик для пожара, когда происходит подключение к порту ( Линия 2 ). Мы используем Порты
Атрибут этого объекта события, чтобы схватить порт и хранить его в переменной ( Линия 4 ). Далее мы добавляем сообщение
Обработчик на порту выполнять расчет и вернуть результат к основной нити ( Линия 7 и строка 25 ) Как это:
onmessage = (e) => { let numbers = e.data; let startTime = new Date().getTime(); let len = numbers, sum = 0, i; if (len === 0) { return 0; } for (i = 0; i < len; i++) { sum += i; } let endTime = new Date().getTime(); postMessage({average: sum / len, time: ((endTime - startTime) / 1000)}) };
Прекращение веб-работника
Если вам нужно немедленно прекратить рабочий работник от основного потока, вы можете сделать это, позвонив на работу работника прекратить Метод:
// terminating a web worker instance myWorker.terminate();
Рабочий поток немедленно убит без возможности завершить свою деятельность.
Нерест веб-работника
Рабочие могут создавать больше рабочих, если хотят. Но они должны быть проведены в том же источнике, что и родительская страница.
Импорт сценариев
Рабочие потоки имеют доступ к глобальной функции, ImportCripts ()
, что позволяет им импортировать сценарии.
importScripts(); /* imports nothing */ importScripts('foo.js'); /* imports just "foo.js" */ importScripts('foo.js', 'bar.js'); /* imports two scripts */ importScripts('//example.com/hello.js'); /* You can import scripts from other origins */
Рабочая демо
Мы обсудили некоторые из подходов выше для достижения Async-программирования, чтобы наш UI не заблокирован из-за любой тяжелой вычислительной задачи. Но есть некоторые ограничения для этих подходов. Таким образом, мы можем использовать веб-работники для эффективного решения этих проблем.
Здесь вы увидите 3 раздела:
- Блокирующий код .: Когда вы нажимаете на Рассчитать среднее , погрузчик не отображается и через некоторое время вы видите окончательный результат и принятый во время. Это потому, что как только Средний метод вызывается, я вызвал Showloader Метод также. Но поскольку js – это одиночная резьба, он не будет выполнен Showloader до тех пор, пока выполнение среднего выполняется. Итак, вы не сможете увидеть загрузчик в этом случае.
- ASYNC код : В этом я попытался достичь ту же функциональности, используя метод SettimeOut и поместив все выполнение функции в контур событий. Вы увидите загрузчик в этом случае, но ответ требует времени по сравнению с методом, определенным выше.
- Веб-пользователь : Это пример использования веб-работника. В этом вы увидите загрузчик, как только вы нажимаете на вычисление среднего, и вы получите ответ одновременно с методом 1, для того же номера.
Вы можете получить доступ к исходному коду для того же здесь Отказ
Расширенные концепции
Существуют некоторые современные концепции, связанные с веб-работниками. Мы не будем обсуждать их подробно, но приятно знать о них.
- Политика безопасности содержимого – У веб-работников есть свой собственный контекст исполнения, независимый от документа, который их создал, и из-за этой причины они не регулируются политикой безопасности содержания родительской нити/работника. Исключением из этого является если происхождение рабочего сценария является глобально уникальным идентификатором (например, если его URL имеет схему данных или BLOB). В этом случае работник наследует политику безопасности содержания документа или работника, созданного его.
- Передача данных на работников и от работников – Данные, переданные между основным и рабочим потоком, является скопирован И не поделился. Объекты сериализуются, поскольку они передаются рабочему, и впоследствии десериализовались на другом конце. Страница и работника Не разделяйте тот же экземпляр поэтому конечный результат в том, что дубликат создается на каждом конце. Браузеры реализованы Структурированные клонирование алгоритм для достижения этого.
- Встроенные работники – Вы также можете встроить код работника внутри веб-страницы (HTML). Для этого вам нужно добавить тег скрипта без атрибута SRC и назначить его неизаятельным типом MIME, например:
embedded worker
Есть много случаев использования для использования веб-работников в нашем приложении. Я только что обсудил небольшой сценарий. Надеюсь, это поможет вам понять концепцию веб-работников.
[Ссылки]
GitHub Repo: https://github.com/bhushangoel/webworker-demo-1 Веб-документ в действии: https://bhushangoel.github.io/webworker-demo-1/ JS Demo Showcase: https://bhushangoel.github.io/
Спасибо за чтение.
Счастливое обучение:)
Первоначально опубликовано www.thehungrybrain.com .