如何使两个承诺同步执行?

时间:2019-09-07 12:25:45

标签: javascript node.js

我正在尝试从Redis获取一些数据,对其进行处理,然后将其存储回去。所以我有两个打电话给redis的电话:

_.each(guids, async (guid) => {
            const targetRecordSl = await this.redisConn.ft_searchAsync(this.TargetIndex, [`@guid:{${guid}}`, 'RETURN', 1, 'sl']);
            console.log('Trying to add sl:' + slId + ' to: '+guid+ ' existing value:'+ targetRecordSl[2][1]);
            let sl = '';
            if(targetRecordSl[2][1] != '_null' && !targetRecordSl[2][1].includes(slId)) {
                sl = targetRecordSl[2][1] + ', ' + slId;
            } else {
                sl = slId;
            }
            const response = await this.redisConn.ft_addAsync(this.TargetIndex, [`${this.TargetIndex}:${guid}`, 1, 'REPLACE', 'PARTIAL', 'FIELDS', 'sl', sl]);
            console.log(response);

第一个查询执行循环的所有迭代,而无需等待第二个查询完成:

Trying to add sl:11 to: P6d43d914bea8b91ece2a0a3c081b9b85 existing value:10
Trying to add sl:10 to: P6d43d914bea8b91ece2a0a3c081b9b85 existing value:10
Trying to add sl:9 to: P24e58b30a0658b8f0e5f9ce1ca0acc1f existing value:9
Trying to add sl:8 to: P7345d54686bfd491747eefd4e05d0362 existing value:8
OK
OK
OK
OK

这不是我想要的。我希望一个诺言等待另一个诺言完成:

Trying to add sl:11 to: P6d43d914bea8b91ece2a0a3c081b9b85 existing value:10
OK
Trying to add sl:10 to: P6d43d914bea8b91ece2a0a3c081b9b85 existing value:10
OK
Trying to add sl:9 to: P24e58b30a0658b8f0e5f9ce1ca0acc1f existing value:9
OK
Trying to add sl:8 to: P7345d54686bfd491747eefd4e05d0362 existing value:8
OK

请咨询。

2 个答案:

答案 0 :(得分:2)

也许您可以尝试使用普通的for循环来做到这一点:

for (const guid of guids) {
  const targetRecordSl = await this.redisConn.ft_searchAsync(this.TargetIndex, [`@guid:{${guid}}`, 'RETURN', 1, 'sl']);

  console.log('Trying to add sl:' + slId + ' to: ' + guid + ' existing value:' + targetRecordSl[2][1]);

  let sl = '';
  if (targetRecordSl[2][1] != '_null' && !targetRecordSl[2][1].includes(slId)) {
    sl = targetRecordSl[2][1] + ', ' + slId;
  } else {
    sl = slId;
  }

  const response = await this.redisConn.ft_addAsync(this.TargetIndex, [`${this.TargetIndex}:${guid}`, 1, 'REPLACE', 'PARTIAL', 'FIELDS', 'sl', sl]);

  console.log(response);
}

如果这是顶级代码,则可以尝试:

async function processGuids(guids) {
    for (const guid of guids) {
        const targetRecordSl = await this.redisConn.ft_searchAsync(this.TargetIndex, [`@guid:{${guid}}`, 'RETURN', 1, 'sl']);

        console.log('Trying to add sl:' + slId + ' to: ' + guid + ' existing value:' + targetRecordSl[2][1]);

        let sl = '';
        if (targetRecordSl[2][1] != '_null' && !targetRecordSl[2][1].includes(slId)) {
            sl = targetRecordSl[2][1] + ', ' + slId;
        } else {
            sl = slId;
        }

        const response = await this.redisConn.ft_addAsync(this.TargetIndex, [`${this.TargetIndex}:${guid}`, 1, 'REPLACE', 'PARTIAL', 'FIELDS', 'sl', sl]);

        console.log(response);
    }
}

processGuids(guids)
    .then(() => {
        console.log('JOB DONE!!')
        // Here goes your following code (if it has to be executed after processing all guids)
    });

答案 1 :(得分:0)

好问题!我已经对如何异步遍历请求进行了一些研究,并在异步迭代器和生成器上找到了一些文章,这些文章提供了对每个guidfetch进行迭代的可能性继续进行下一个guid

因此,我对您的代码做了一些修改。首先,我创建了一个函数fetchGuid,该函数可提取单个guid

async function fetchGuid(guid) {
    const targetRecordSl = await this.redisConn.ft_searchAsync(this.TargetIndex, [`@guid:{${guid}}`, 'RETURN', 1, 'sl']);
    console.log('Trying to add sl:' + slId + ' to: '+guid+ ' existing value:'+ targetRecordSl[2][1]);
    let sl = '';
    if(targetRecordSl[2][1] != '_null' && !targetRecordSl[2][1].includes(slId)) {
        sl = targetRecordSl[2][1] + ', ' + slId;
    } else {
        sl = slId;
    }
    const response = await this.redisConn.ft_addAsync(this.TargetIndex, [`${this.TargetIndex}:${guid}`, 1, 'REPLACE', 'PARTIAL', 'FIELDS', 'sl', sl]);
    return response.
}

这是一个异步生成器函数,它将创建一个我们可以循环的迭代器。这使我们能够像您希望的那样运行顺序循环。它会一直运行到yield出现,然后等待直到再次被调用。

async function* iterateGuids(guids) {
    for (guid of guids) {
        const response = await fetchGuid(guid);
        yield response;
    }
}

现在,第三个功能是您可以从中运行代码的地方。 getSequentialGuids调用iterateGuids函数并创建一个迭代器。然后,它使用for await ... of异步遍历迭代器中的每个位置,在这种情况下,这是一个从HTTPRequest解析的承诺。

async function getSequentialGuids(guids) {
    const responses = iterateGuids(guids);
    for await (const response of responses) {
        console.log(response);
    }
}

因此,最后使用guids函数调用您的getSequentialGuids数组,如下所示,并看到魔术发生了。

getSequentialGuids(guids);

这对我来说也是使用异步生成器for await ... of语法的学习经历。因此,如果您遇到一些问题或有更多问题,请告诉我,以便我可以帮助您和我自己,从中学到东西。