Как запустить интенсивные операции ЦП в рабочем потоке в Angular 4 и обновить прогресс в пользовательском интерфейсе?

Я вижу пару примеров, которые Джейсон Теплиц написал об использовании веб-работников в Angular 2. Angular 4 CLI теперь поддерживает платформенный рабочий, который запускает приложение в рабочем потоке. Хорошим примером этого является факторный пример. Или это шаг за шагом пример.

  • Использование platform-worker гарантирует, что все длинные вычислительные операции выполняются в веб-работнике? Или мне нужно создать еще один Angular модуль (а не модуль приложения), который использует платформенный рабочий для выполнения длительной операции вычисления? В результате будут два модуля, один для приложения, а другой для длительной операции?

  • Должен ли я создать отдельный Worker, как в этом пример, чтобы создать рабочие потоки?

  • Как обновить пользовательский интерфейс с ходом выполнения операции? Я предполагаю, что если длинная операция выполняется в цикле for, у нее не будет возможности сообщить UI о прогрессе, пока этот цикл не будет завершен? Должен ли я разделить длинную операцию на несколько небольших операций и обновить пользовательский интерфейс?

Ответ 1

Я постараюсь предоставить хотя бы ответ заполнителя, пока мы не сможем получить более исчерпывающий:

  • Да, platform-worker отключает ваш код от потока пользовательского интерфейса.

Более длинное объяснение

Использование platform-worker гарантирует, что ваш код запущен в веб-работнике. Angular все еще должен запускать некоторый код на этой стороне вещей, в потоке пользовательского интерфейса, но platform-worker в основном перемещает весь ваш код и логику в рабочий поток, вычисляет все вызовы DOM, и когда настало время, он называет ваш DOM магией. Но это не вся картина, так что рассмотрим вещи немного больше.

  1. Отдельный рабочий: зависит, но TL; DR: да.

Более длинное объяснение

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

Если у вас тяжелое приложение (например, огромная таблица со многими связями или многие компоненты, выполняющие множество задач с процессором), это может считаться тяжелым приложением. Он определенно платит, чтобы разгрузить его работнику. Но если ваше приложение не так сложно, и только определенная работа, вы можете рассмотреть возможность разделения вашего приложения и вашей работы. Даже если вы разгрузите приложение для рабочего, если есть задача, которая на какое-то время убивает всего работника, все ваше приложение, пользовательский интерфейс и все, ненадолго перестают отвечать. Конечно, вы можете прокручивать и щелкать, но angular, так как он находится в том же потоке, что и длительная тяжелая синхронная задача, не имеет шансов ответить. Это почти так же, как если бы все было запущено в потоке пользовательского интерфейса.

Вот почему я считаю, что вы можете создать отдельного Работника для своей тяжелой задачи. Вам нужно дать место Angular для дыхания тоже.

  1. Можете ли вы сделать обновления пользовательского интерфейса: зависит.

Более длинное объяснение

Вы также беспокоитесь, как вы будете обновлять вещи в цикле for. Ну, если у вас есть длительная синхронная задача - тогда вам нужно предоставить обновления между циклами в этом рабочем месте.

Почему? Потому что, если вы не можете перестать работать (синхронизировать), тогда Angular не сможет выйти из вашего кода (внутри веб-мастера) и отправить сообщение в поток пользовательского интерфейса (и часть пользовательского интерфейса angular) и обновить пользовательский интерфейс. Или, если у вас есть отдельная рабочая работа, она просто не сообщит Angular, как далеко она прошла.

Итак, если все ваше приложение находится в веб-рабочем (вместе с логикой с большим процессором), вы можете, например. каждые 100 итераций, обновите некоторые локальные наблюдаемые или подобные, и установите следующий цикл, который будет запущен позже в setTimeout. Он должен дать Angular возможность отправить обновление этого обязательного значения в средство визуализации DOM, которое, в свою очередь, может уведомить об этом поток пользовательского интерфейса.

И если ваше приложение находится в отдельном рабочем месте, чем ваша фактическая задача с процессором, вам все равно нужно отправить это обновление каждые 100, скажем, 100 итераций, в ваше приложение Angular.

Таким образом, ваше приложение Angular все еще реагирует на запросы, и у вас все еще может быть служба, которая слушает обновления хода работ у этого рабочего и обновляет пользовательский интерфейс. (опять же, например, каждые 100 циклов запускают сообщение на другой конец рабочего). Например. вы просто показываете lil spinner где-то, когда пользователь нажимает, он показывает, насколько далеко стоит задача, и пользователь может использовать другие части приложения.

Если вы предоставите более подробную информацию о своей интенсивной задаче ЦП, возможно, кто-то может дать лучший ответ. Я надеюсь, что это поможет немного починить ситуацию.