Как реализовать простую очередь в NodeJS?

125
04 декабря 2020, 09:50

Допустим, у нас есть 10 задач, которые нужно выполнить параллельно, но оперативной памяти (os.freemem()) хватает только на 7. Можно ли как-то поставить выполняться 7 задач, но чтобы остальные ждали своей очереди и запускались только когда появляется свободная для выполнения память?

Answer 1

Функция для запуска задач в указанном количестве:

function sequence(ts, limit) {
  return new Promise(resolve => {
    var res = [];
    var index = 0, done = 0;
    function go() {
      var i = index++;
      ts[i] && ts[i]().then(
        result => res[i] = {result},
        error => res[i] = {error}
      ).finally(
        () => {
          if (++done === ts.length) {
            resolve(res);
          } else {
            go();
          }
        }
      )
    }
    for (var q=0; q<limit; ++q) {
      go()
    }
  });
}

Пример использования:

async function showAll(ids) {
  var res = await sequence(ids.map(id => () => getItem(url, id)), 10);
  document.querySelector(".result").innerHTML = res.map(({result, error}) => `
    <div style="background:${error ? 'red' : 'green'}">${escapeHTML(error || result)}</div>
  `).join("");
}

Источник: https://vk.com/wall-102547801_290

Запускаемый пример:

function sequence(ts, limit) { 
  return new Promise(resolve => { 
    var res = []; 
    var index = 0, done = 0; 
 
    function go() { 
      var i = index++; 
 
      ts[i] && ts[i]().then( 
        result => res[i] = {result}, 
        error => res[i] = {error} 
      ).finally( 
        () => { 
          if (++done === ts.length) { 
            resolve(res); 
          } else { 
            go(); 
          } 
        } 
      ) 
    } 
 
    for (var q=0; q<limit; ++q) { 
      go() 
    } 
  }); 
} 
 
var escapeHTML = (function () { 
  var div = document.createElement('div'); 
 
  return function escapeHTML(text) { 
    div.textContent = text; 
    return div.innerHTML; 
  } 
})(); 
 
function getItem(id) { 
  return new Promise((resolve, reject) => { 
    var isOk = Math.random() > .01; 
    setTimeout(isOk ? resolve : reject, Math.random() * 100, isOk ? id : "?"); 
  }); 
} 
 
function getItem(id) { 
  return new Promise((resolve, reject) => { 
    var section = document.querySelector(".original"); 
    var div = section.children[id]; 
 
    if (!div) { 
      section.insertAdjacentHTML('beforeend', "<div></div>".repeat(id - section.children.length + 1)); 
      div = section.children[id]; 
    } 
 
    div.style.background = 'yellow'; 
 
    setTimeout(Math.random() > .1 
      ? () => { resolve(id);   div.textContent = id;    div.style.background = 'green'; } 
      : () => { reject("?");   div.textContent = "?";   div.style.background = 'red';   }, 
      Math.random() * 1000 
    ) 
  }); 
} 
 
async function showAll(ids) { 
  var res = await sequence(ids.map(id => () => getItem(id)), 5); 
 
  document.querySelector(".result").innerHTML = res.map(({result, error}) => ` 
    <div style="background:${error ? 'red' : 'green'}">${escapeHTML(error || result)}</div> 
  `).join(""); 
} 
 
showAll(Array(100).fill().map((x, i) => i))
section { 
  overflow: hidden; 
} 
 
section > div { 
  height: 1em; 
  width: 3ch; 
  float: left; 
  margin: .125em; 
  background: silver; 
  line-height: 1em; 
  text-align: center; 
  font-family: monospace; 
  color: white; 
}
<section class="original"></section> 
<hr> 
<section class="result"></section>

READ ALSO
Нужна помощь с Web чатом на Java и WebSocket

Нужна помощь с Web чатом на Java и WebSocket

Сама настройка веб сокета

126
Вставка данных с помощью ajax

Вставка данных с помощью ajax

На странице есть 2 таблицы, мне туда нужно вставлять ордера из БД, делаю с помощью ajaxДанные вставляются, но почему-то первый столбец в таблице...

93
Регулярные выражения для дат в Javascript

Регулярные выражения для дат в Javascript

Задача Есть инпут, который принимает текст в формате дате в виде ДДММ

123