Блокировка вокруг асинхронного метода JavaScript - PullRequest
0 голосов
/ 25 января 2019

У меня есть асинхронный метод run, который принимает задачи, но не должен вызываться одновременно, поскольку он порождает отдельный ресурсоемкий процесс для каждой задачи.

Для этого я попытался реализоватьпрокси-функция, queue, которая вызывается другим модулем при появлении новых задач.Эта функция должна позволять самое большее один фрагмент асинхронного кода внутри функции run в любое время.Т.е. каждая задача должна получить блокировку, которая не освобождается до завершения обработки.

Мой подход пока такой:

let promise;

const queue = (...args) => {
    promise = (async() => {
        try {
            await promise;
        } catch (e) {
            // returned promised is consumed elsewhere hence empty catch block
        }
        return run(...args);
    })();
    return promise;
};

const run = async (task) => {
    console.log('Running ' + task);
    // some resource intensive process is started
    return new Promise((resolve, reject) => {
        setTimeout(resolve, 2000);
    });
};

// calling module without error handling
(async() => {
    await Promise.all([1, 2, 3].map(queue));
    console.log('All tasks finished');
})();

К сожалению, это не позволяет мне видеть, когда очередь пуста илисколько задач в настоящее время ожидает в очереди.

Есть ли лучший способ решения этой проблемы?

1 Ответ

0 голосов
/ 26 января 2019

Я думаю, что ваше решение довольно хорошее, и, возможно, вы могли бы просто установить какой-нибудь счетчик очереди для отслеживания текущей задачи и задач, оставшихся в очереди. Я думаю, что это может быть немного упрощено, если вы полностью игнорируете Promise.all и map, возможно, что-то вроде этого:

// custom Promise method that takes an array of tasks 
// and the function to run said tasks individually

Promise.each = async function(tasks, fn) {
  for (const task of tasks) {
    // you can track progress in here by updating some counter,
    // or calling some update function
    await fn(task);
  }
  console.log('All tasks finished');
};

const run = (task) => {
    console.log('Running ' + task);
    // some resource intensive process is started
    return new Promise((resolve, reject) => {
        setTimeout(() => {
          asyncLock = false;
          resolve();
        }, 2000);
    });
};

Promise.each([1, 2 ,3], run);
...