У всех возникают некоторые сомнения, когда они видят в названии слово «Воин». Я не буду здесь слишком много объяснять, просто скажу одно: поскольку это старый проект (вы знаете, он старый и очень старый), можно действительно сказать, что он влияет на все тело.
Но очень скоро я молниеносно принял решение и просто выбрал файл.CTRL+A
,ПотомDelete
Ах, эта волна операций, можно сказать, резвая и предельно уверенная.
Хотя позже я заплатил цену в 100 миллионов за свою уверенность в себе, но, к счастью, результат меня радует, а сегодня еще и за поведение этого воина.WorkerЧастично сделать итоговую запись.
Сегодня Worker описывается с трех сторон:
- что (что такое рабочий?)
- почему (зачем использовать?)
- Как (как использовать?)
Что - что такое рабочий?
мы все знаемJavaScript
Это однопоточный язык, что означает, что все задачи могут выполняться только в одном потоке, и одновременно может выполняться только одна задача, что вызывает проблему.Когда в потоке слишком много задач, он приведет к блокировке задачи. С развитием аппаратного обеспечения (многоядерный ЦП) и интерфейсных систем (сложные требования и множество функций) это вызовет множество неудобств.Worker
Именно для решения этих проблем.
Обзор
Worker
Можно создать отдельный поток от основного потока. пройти черезWorker
Созданная нить работает на заднем плане, основной нить может назначать некоторые задачи к этой независимой потоке для выполнения, а два не мешают друг другу.Worker
После выполнения задачи в потоке ее можно пройти черезmessage
для отправки результата выполнения в основной поток.Поскольку Worker — это независимый поток, его глобальный контекст такой же, как тот, который мы обычно используем при его выполнении.windowРазличные объекты можно разделить на два типа в зависимости от глобального контекста Worker:
-
Worker: Выделенный рабочий процесс, который используется только страницей, на которой в данный момент выполняется скрипт.При закрытии этой страницы текущий рабочий процесс также будет закрыт, и соответствующий контекст
DedicatedWorkerGlobalScope
-
sharedWorker: общий рабочий процесс, который может использоваться несколькими страницами. Текущий рабочий процесс будет закрыт, когда будут закрыты все связанные страницы. Соответствующий контекст
SharedWorkerGlobalScope
В то время я использовал выделенного рабочего, и мы должны чаще использовать его в нашей повседневной работе, поэтому в этой статье обсуждается только этот выделенный рабочий.
будь осторожен
Сначала давайте посмотрим, как создать простой рабочий объект.
const worker = new Worker( url )
1. ограничение гомологии
Файл сценария, назначенный рабочему потоку для запуска, должен иметь то же происхождение, что и файл сценария основного потока.
2. Ограничения доступа к API
Выше мы упоминали, что глобальный объект, в котором находится рабочий поток, отличается от основного потока, поэтому некоторые объекты и функции в основном потоке не могут быть прочитаны. Здесь мы кратко перечислим несколько общих
- недоступен:
window
document
alert()
confirm()
- Доступный:
navigator
location
XMLHttpRequest
fetch
Более подробные разрешения доступа к API можно посмотреть на официальном сайте:Нажмите здесь, чтобы перейти напрямую
3. лимит файлов
Рабочий процесс не может получить доступ к локальным ресурсам, входящий URL-адрес должен бытьИнтернет-ресурсы. Поэтому для локальных скриптов мы можем преобразовать его вBlob URLиспользовать
Зачем - зачем использовать?
Фактически, выше я кратко упомянул, что Worker может совместно использовать некоторые ресурсоемкие и трудоемкие задачи в основном потоке, что является основной причиной, по которой нам необходимо его использовать.
Для этого проекта, который я принял, моя отправная точка для использования Worker в основном из-за следующих двух моментов:
- В проекте есть большой визуальный экран, который охватывает множество данных, включая организационные данные, картографические данные и различные статистические данные. Объем этих данных огромен, особенно данные карты и организационной структуры, и есть некоторые операции обхода данных карты и организационных данных. Самое главное, что все запросы к этим интерфейсам запрашиваются после входа в систему, что приводит к очень серьезной проблеме: большой экран должен полностью отображаться примерно за 7-10 секунд, хотя в середине есть эффект перехода загрузки. Но все же неудачный опыт, на мой взгляд.
- В проекте есть интерфейс опроса, который должен регулярно запрашивать данные для обновления страницы. Это приводит к небольшой задержке некоторых кликов при частых запросах.
Как - как использовать?
Код товара, потому что компания не выходит для всех, чтобы увидеть. Итак, мы делаем здесь с простой пример, который мы чувствуем
Этапы реализации:
1. Создайтеindex.html
документ
<script type="module">
// 引入worker脚本
import workerScript from './worker.js'
// 创建worker线程,参数为脚本的url
// 这里需要注意一下,这里的url是Blob URL,具体原因我们在上文已经说过
const worker = new Worker(workerScript);
// 主线程和子线程进行通信
worker.postMessage('http://juejin.cn')
// 获取子线程发送来的消息
worker.onmessage = (msg) => {
const { data } = msg
document.body.innerHTML = data
}
// 监听worker的错误事件
worker.onmessageerror = (error) => console.log(error)
</script>
2. Создайтеworker.js
документ
// 需要在worker中执行的脚本
const workerScript = () => {
onmessage = (msg) => {
if (msg.data) {
// 接收到主线程的消息之后,与主线程进行通信
postMessage(`我接受到你的参数了,我再吐给你${msg.data}`);
}
};
};
// 将上述执行脚本转换为字符串
let code = workerScript.toString();
// 对字符串进行分割,取到onmessage部分的函数声明
code = code.substring(code.indexOf("{") + 1, code.lastIndexOf("}"));
// 将字符串转换为Blob URL
const blob = new Blob([code], { type: "application/javascript" });
const blobUrl = URL.createObjectURL(blob);
// 导出生成的Blob URL
export default blobUrl;
Нужно еще раз подчеркнуть в этом файле, что мы создаем
Worker
Когда мы можем выполнять только сетевые ресурсы, мы не можем загружать локальные ресурсы, поэтому, когда мы просто экспортируем этот файл js, будет сообщено об ошибке, похожей на сбой загрузки ресурсов.
Далее мы преобразуем исполняемый код в
Worker
узнаваемыйBlob URL
Эффект исполнения
Делайте сетевые запросы с работниками
немного правееworker.js
С помощью нескольких настроек вы можете
// 需要在worker中执行的脚本
const workerScript = () => {
onmessage = (msg) => {
// 发送网络请求
const response = await fetch(msg.data, {
method: "post",
body: `yes = 1`,
}).then((res) => res.json);
if (response) {
// TODO 可以在这里对数据进行处理,然后发送给主线程
postMessage(`我数据处理完成了,给你用吧`);
}
};
// 将上述执行脚本转换为字符串
let code = workerScript.toString();
// 对字符串进行分割,取到onmessage部分的函数声明
code = code.substring(code.indexOf("{") + 1, code.lastIndexOf("}"));
// 将字符串转换为Blob URL
const blob = new Blob([code], { type: "application/javascript" });
const blobUrl = URL.createObjectURL(blob);
// 导出生成的Blob URL
export default blobUrl;
Мы видим, что этот запрос немного отличается от запроса, который мы обычно видим на этой панели, перед ним стоит маленькая шестеренка, которая доказывает, что запрос сделан в рабочем потоке, и на этом мы закончили.
Практика в проекте
Благодаря вышеуказанным операциям в этом проекте скорость загрузки большого визуального экрана после входа в систему стабильна на уровне3~5s, скорость увеличилась40%о.
Конечно это всего лишь небольшой момент в оптимизации, конечно я тоже использую React'ы в проектеmemo
,useMemo
,useCallback
и другие методы были оптимизированы соответствующим образом.
над
worker.js
Это пакет, который я сделал в проекте, поэтому вы также можете использовать его непосредственно в своем проекте. Шаги для использования:
- Буду
worker.js
Скопируйте файл в соответствующую папку текущего проекта.- Ниже комментария TODO вы можете добавить собственную обработку копирования больших данных в проекте, таких как обход, рекурсия и т. д., и передать ее в основной поток через postMessage после завершения обработки.
- пройти в основной файл
import xxx from './worker'
Представьте сценарий выполнения
- пройти через
new Worker(xxx)
Создать рабочий поток- пройти через
onmessage
Метод прослушивает события связи между потоками (обычно для отображения обработанных данных, переданных рабочим потоком).
Суммировать
Мы видим, что на самом деле использование Worker очень простое, вам нужно всего лишь добавить еще несколько строк кода в соответствующий проект, чтобы выполнить некоторые операции, влияющие на производительность страницы, почему бы не сделать это?
и дляОптимизация производительности на уровне кодаС этой точки зрения, я думаю, что как программисты, мы должны думать, когда пишем код каждый день. Мы не можем просто делать это для удовлетворения потребностей. Иногда мы также думаем о том, повлияла ли работа этого кода на то, когда он доходит до взаимодействия со страницей, есть ли способ оптимизировать его на уровне кода? (Кажется, это вопрос, о котором говорят старики, но он действительно имеет смысл! Как говорится, «Если ты не слушаешь стариков, ты будешь страдать перед собой»). Если есть возможность оптимизации, то изучите сопутствующие технологии и сформулируйте планы, которые очень полезны для личностного роста (все QAQ научились у больших парней)
Повседневное мышление важно, но если вы сделаете из размышлений определенный результат, эффект будет очень хорошим~,double up! (делаю сам, поэтому имею личный опыт)
Последнее предложение: xdm, давай!