承诺迭代一个链接数组,使用 mercury-client 解析它们并将解析的内容推送到一个新数组中

Promise to iterate over an array of links, parsing them using mercury-client and pushing the parsed content into a new array

我有一个链接数组,我想使用 mercury-client 解析其内容,并将结果推入 articles 数组。

* parseLinks() {
  const links     = yield this.getInboxMessages() // It will be ['link1', 'link2', ..., 'linkN']
  const articles  = []

  return new Promise((resolve, reject) => {
    for (let link of links) {
      mercury.parse(link).then((data) => {
        articles.push(data)
      })
    }

    resolve(articles)
  })
}

我看不出有什么问题,因为我只得到 []。我试图将 Promise 移动到 for..of 内,但结果保持不变。

通过删除循环并使其仅解析 links 数组的第一个索引,我没有遇到任何问题。

你得到 [] 篇文章是因为你调用 resolve(articles) sync'ly 而你的 for 循环将数据异步推送到那里。与其将已解决的 data 推入您的文章,不如将 mercury.parse(link) 承诺推入一个数组。您最终会得到一系列待解决的 mercury-client promises。然后,您可以在该数组上使用 Promise.all 并仅在所有依赖的承诺都已解决时才解决 articles

你在 articles 被填满之前解决得太早了。

您可以将整个 return 块替换为:

return Promise.all(links.map(link => mercury.parse(link)));

这将 return 只有在每 link 被处理一次后,一个已解决的承诺。

如果(且仅当)mercury.parse 函数可以处理作为裸函数引用传递而无需将 mercury 作为 this 上下文变量传递,您可以简化进一步:

return Promise.all(links.map(mercury.parse));

您可以通过 Array.prototype.reducePromise.all 组合来实现。如下所示。

function parseLinks () {
  const links = [....]

  return Promise.all(links.reduce((promises, link) => {
    return promises.concat(mercury.parse(link))
  }, []))
}

parseLinks().then(links => console.log(links))