for..in цикл для асинхронных задач в Javascript - PullRequest
0 голосов
/ 09 мая 2019

У меня есть ассоциативный контейнер (ключ / значение, "хэш"). Я перебираю его, используя цикл for..in:

for (key in container) {
   doSomethingWith(key, container[key]
}

Теперь я хочу, чтобы doSomethingWith () возвращала обещание (Q или стандартное), и я хочу выполнять итерации последовательно, а не параллельно. То есть я хочу, чтобы каждый вызов doSomethingWith () разрешал свое обещание перед повторным вызовом.

Как мне это сделать?

  1. Есть ли способ перебирать ключи, не прибегая к Object.keys () (который в моем случае довольно длинный) и индексам? Помог ли новый класс Map?

  2. Это может быть уже кем-то написано. Кроме того, если я хочу иметь ограниченный параллелизм (например, что-то в процессе выполнения чего-то 10) в духе make -j 10), сложность возрастает, поэтому где-то должна существовать зрелая реализация.

  3. Как именно я это делаю? Я предпочитаю использовать вспомогательную функцию, которая вызывает себя из метода done ():


function forEachKey(obj, doSomething) {
    const q = Q.defer()
    const keys = Object.keys(obj)
    const idx = 0
    const helper = () =>
       if (idx < keys.length) {
           doSomething(idx).done(helper)
           idx += 1
       }
       else
       {
          q.resolve()
       }
}

Ответы [ 3 ]

1 голос
/ 09 мая 2019

Это очень простая демонстрация, но я думаю, что это показывает, как можно использовать async / await для получения того, что вам нужно.

const container = {
  name: "test",
  value: "test2"
};

const doSomethingWith = (x, y) => new Promise((resolve, reject) => {
  console.log(x);
  resolve(x);
});

(async() => {
  for (let key in container) {
    await doSomethingWith(key, container[key]);
  }
})();
1 голос
/ 09 мая 2019

Поскольку я нахожусь на узле 4.9.1, я не могу использовать async / await. Итак, вот мое собственное мнение, используя yield:

function* keyGenerator(obj)
{
    for (const key in obj)
    {
        yield key
    }
}

exports.asyncForIn = function (obj, doSomething)
{
    const keyGen = keyGenerator(obj)
    const q = Q.defer()

    const rec = () => {
        const i = keyGen.next()
        if (!i.done)
        {
            doSomething(i.value).done(rec, (x) => q.reject(x))
        }
        else
        {
            q.resolve()
        }
    }
    rec()
    return q.promise
}
1 голос
/ 09 мая 2019

Вам нужно будет составить цепочку обещаний. Вот пример с уменьшением:

Object.keys(obj).reduce((promiseSoFar, key) => 
  promiseSoFar.then(() => doSomethingWith(key, container[key])
, Promise.resolve());

Есть ли способ перебирать ключи, не прибегая к Object.keys () (который в моем случае довольно длинный) и индексам

Я не уверен, что такое отвращение к Object.keys, но да, вы можете построить цепочку обещаний без Object.keys

let promiseSoFar = Promise.resolve();
for (let key in container) {
   promiseSoFar = promiseSoFar.then(() => doSomethingWith(key, container[key]));
}
Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...