具有异步/等待功能的三层深度图

时间:2019-12-02 06:58:47

标签: node.js promise async-await

我需要从三个表(使用nodejs和mysql),帖子,评论和回复中获取数据,以下是我尝试但未获得预期结果的方法。任何人都可以查看我的代码。

try {
  feeds = await db.getPosts('', offset = 0, limit = 3);
  await Promise.all(
    feeds.map(async(feed, i) => {
      let cmts = await cmnt.getCommentsByPostId(feed.id);

      feeds[i].comments = JSON.stringify(cmts);

      await Promise.all(
        feeds[i].comments = cmts.map(async(cmt, j) => {
          cmts[j].replies = await cmnt.getRepliesByCommentId(cmt.id);
        })
      )
    })
  )

} catch (err) {
  console.log(err)
}

我需要feeds变量中的所有内容(帖子,评论及其回复),以便可以在模板中使用多个(循环内循环)进行迭代。我还尝试在foreach内部的模板中调用getCommentsByPostId()循环,但没有用。

2 个答案:

答案 0 :(得分:1)

您的代码有几个问题,让我们尝试解决它们:

(1)因为第一个映射函数中没有返回任何内容(即Promise { undefined }),所以您收到的注释为undefined,因此第一个Promise.all正在立即解析而不是等待评论和答复解决。

要解决此问题,您必须返回第二个Promise.all以做出以await cmnt.getRepliesByCommentId(cmt.id)调用结尾的承诺链

(2)另外,您正在第二个feeds[i].comments = cmts.map(async(cmt, j) => {中分配Promise.all。你不应该那样做。

(3)最后,当您将cmts分配给feeds[i]时进行字符串化时,您将丢失其引用,因此稍后在执行cmts[j].replies = ...时,该更改将赢得在feeds[i].comments中无效。

try {
  feeds = await db.getPosts('', offset = 0, limit = 3);
  await Promise.all(
    feeds.map(async(feed, i) => {
      let cmts = await cmnt.getCommentsByPostId(feed.id);

      feeds[i].comments = cmts; // (3)

      return Promise.all( // <-------------------- (1)
        cmts.map(async(cmt, j) => { // <---------- (2)
          cmts[j].replies = await cmnt.getRepliesByCommentId(cmt.id);
        })
      )
    })
  )

} catch (err) {
  console.log(err)
}

答案 1 :(得分:0)

第一个Promise.all看起来不错,您将一个promise数组放到Promise.all上,很好。 但是,在第二个块中,您对第一个块的操作与此不同。

Promise.all需要一个promise数组作为第一个参数。在代码中,您将void的值放在Promise.all上,因为分配操作(feeds[i].comments = ...返回“ void”)。

我建议按照自己的方式解决

try {
  feeds = await db.getPosts('', offset = 0, limit = 3);
  await Promise.all(
    feeds.map(async (feed, i) => {
      let cmts = await cmnt.getCommentsByPostId(feed.id);

      feeds[i].comments = JSON.stringify(cmts); // ????

      await Promise.all( // here
        cmts.map(async (cmt, j) => { // map returns array, in this case in returns Promise<void>[]
          cmts[j].replies = await cmnt.getRepliesByCommentId(cmt.id);
        })
      ) 
      // get all replies of each comments are done!
      feeds[i].comments = cmts; // comment with replies
    })
  )

  console.log(feeds); // feeds includes comment's replies.

} catch (err) {
  console.log(err)
}