for..in循环,用于执行Javascript中的异步任务

时间:2019-05-08 21:17:27

标签: javascript foreach promise hashmap

我有一个关联容器(键/值,“哈希”)。我使用for..in循环遍历它:

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

现在,我希望doSomethingWith()返回一个Promise(Q或标准的Promise),我想顺序地而不是并行地进行迭代。也就是说,我希望每次调用doSomethingWith()都要先解决其诺言,然后再再次调用它。

我该怎么做?

  1. 有没有一种方法可以遍历键而不求助于Object.keys()(在我的情况下这很长)和索引?新的Map类有帮助吗?

  2. 它可能已经有人写过。另外,如果我想限制并发性(例如,按照make -j 10的精神进行10个somethingWith()),那么复杂性就会爆炸,因此成熟的实现必须存在于某个地方。

  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 个答案:

答案 0 :(得分:1)

您需要做出一连串的承诺。这是带有reduce的示例:

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]));
}

答案 1 :(得分:1)

这是一个非常简单的演示,但是我认为这表明如何使用异步/等待来实现您的需求。

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]);
  }
})();

答案 2 :(得分:1)

当我在节点4.9.1上时,我无法使用异步/等待。这是我自己使用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
}