У меня есть задача с интенсивным использованием процессора в 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);
})
}
но безуспешно. Есть идеи, как избежать зависания основного потока?



![Безумие обратных вызовов в javascript [JS]](https://i.imgur.com/WsjO6zJb.png)


Вы можете использовать «Веб-воркеров». Таким образом, вы будете соответствовать стандарту. В основном это будет фоновый поток (например, как BackgroundWorker в более ранней версии C#).
Я не уверен, поддерживает ли текущий node.js это естественным образом, поэтому используйте пакет веб-работников npm
Помимо использования веб-воркеров или чего-то подобного, вы также можете (в зависимости от задачи) разбить работу на более мелкие части, которые обрабатываются и планируются с помощью 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
Верно. Похоже, что gibbs - это функция, которая в конечном итоге займет больше всего времени, поэтому, если вы разделите там цикл iterations на отдельную «пошаговую» функцию, это можно будет запланировать с помощью setImmediate.
это хорошая идея, и в браузере это наверняка сработает! Я использую его с процессом
node.clusterс N> 1 воркерами, и запуск его вworkerили вmasterблокирует виртуальную машину таким же образом, поэтому я должен использовать что-то вроде веб-воркеров в узле ..