Как избежать блокировки виртуальной машины JavaScript задачей, связанной с процессором

У меня есть задача с интенсивным использованием процессора в JavaScript, которая блокирует виртуальную машину при выполнении в Promise:

Примером может быть следующий (попробуйте в браузере):

function task() {
   return new Promise((r,s) => {
      for(var x=0; x < 1000000*1000000; x++) {
          var Y = Math.sqrt(x/2)
      }
      return r(true)
   })
}

Я хотел бы избежать блокировки основного потока виртуальной машины, поэтому я попытался отсоединить, используя setTimeout в Promise, передавая resolve и reject в качестве контекста, например:

function task() {
   return new Promise((r,s) => {
      var self=this;
      setTimeout( function(r,s) {
        for(var x=0; x < 1000000*1000000; x++) {
           var Y = Math.sqrt( Math.sin (x/2) + Math.cos(x/2))
         }
         return r(true);
      },500,r,s);
   })
}

но безуспешно. Есть идеи, как избежать зависания основного потока?

Поведение ключевого слова "this" в стрелочной функции в сравнении с нормальной функцией
Поведение ключевого слова "this" в стрелочной функции в сравнении с нормальной функцией
В JavaScript одним из самых запутанных понятий является поведение ключевого слова "this" в стрелочной и обычной функциях.
Концепция локализации и ее применение в приложениях React ⚡️
Концепция локализации и ее применение в приложениях React ⚡️
Локализация - это процесс адаптации приложения к различным языкам и культурным требованиям. Это позволяет пользователям получить опыт, соответствующий...
Улучшение производительности загрузки с помощью Google Tag Manager и атрибута Defer
Улучшение производительности загрузки с помощью Google Tag Manager и атрибута Defer
В настоящее время производительность загрузки веб-сайта имеет решающее значение не только для удобства пользователей, но и для ранжирования в...
Безумие обратных вызовов в javascript [JS]
Безумие обратных вызовов в javascript [JS]
Здравствуйте! Юный падаван 🚀. Присоединяйся ко мне, чтобы разобраться в одной из самых запутанных концепций, когда вы начинаете изучать мир...
Система управления парковками с использованием HTML, CSS и JavaScript
Система управления парковками с использованием HTML, CSS и JavaScript
Веб-сайт по управлению парковками был создан с использованием HTML, CSS и JavaScript. Это простой сайт, ничего вычурного. Основная цель -...
JavaScript Вопросы с множественным выбором и ответы
JavaScript Вопросы с множественным выбором и ответы
Если вы ищете платформу, которая предоставляет вам бесплатный тест JavaScript MCQ (Multiple Choice Questions With Answers) для оценки ваших знаний,...
2
0
227
2
Перейти к ответу Данный вопрос помечен как решенный

Ответы 2

Вы можете использовать «Веб-воркеров». Таким образом, вы будете соответствовать стандарту. В основном это будет фоновый поток (например, как BackgroundWorker в более ранней версии C#).

Я не уверен, поддерживает ли текущий node.js это естественным образом, поэтому используйте пакет веб-работников npm

это хорошая идея, и в браузере это наверняка сработает! Я использую его с процессом node.cluster с N> 1 воркерами, и запуск его в worker или в master блокирует виртуальную машину таким же образом, поэтому я должен использовать что-то вроде веб-воркеров в узле ..

loretoparisi 15.03.2018 14:41
Ответ принят как подходящий

Помимо использования веб-воркеров или чего-то подобного, вы также можете (в зависимости от задачи) разбить работу на более мелкие части, которые обрабатываются и планируются с помощью setImmediate. Этот пример немного глупый, но вы уловили идею.

function brokenUpTask() {
  let x = 0;  // Keep track of progress here, not in the loop.
  const limit = 1000000;
  const chunk = 100000;
  return new Promise((resolve) => {
    function tick() {  // Work a single chunk.
      let chunkLimit = Math.min(x + chunk, limit);
      for(x = 0; x < chunkLimit; x++) {
        var Y = Math.sqrt(x/2);
      }
      if (x === limit) {  // All done?
        resolve(true);
        return;
      }
      setImmediate(tick);  // Still work to do.
    }
    tick();  // Start work.
   });
}


brokenUpTask().then(() => console.info('ok'));

Спасибо! Моя реальная задача - это вычисление LDA (Latent Dirichlet Allocation, en.wikipedia.org/wiki/Latent_Dirichlet_allocation) в этом конкретном случае. См. Эту реализацию здесь: gist.github.com/loretoparisi/07f3af8114a7a70169511351326064a‌ e

loretoparisi 15.03.2018 14:58

Верно. Похоже, что gibbs - это функция, которая в конечном итоге займет больше всего времени, поэтому, если вы разделите там цикл iterations на отдельную «пошаговую» функцию, это можно будет запланировать с помощью setImmediate.

AKX 15.03.2018 15:28

Другие вопросы по теме