2017-07-17 55 views
3

在下面的代碼中,目標是爲每個帖子填充喜歡字段。我正在查詢帖子表並將帖子轉換爲一個對象。基於這個轉換後的結果集中的值,我查詢了喜歡的表,並試圖動態地將相應的喜歡結果集添加到posts對象,如下所示。帶承諾的MySQL - 損失價值

喜歡的領域似乎成功添加在地圖功能。但是,由於處理承諾時出現了一些問題,因此字段不存在then()代碼塊之外。

任何想法,爲什麼這是?我很感謝有關如何解決此問題的任何幫助。

router.post('/load', (req, res) => { 

    connection.then((conn) => { 
     return conn.query("SELECT userId, postId FROM posts"); 
    }).then((postsRows) => { 

     let posts = postsRows.map((r) => Object.assign({}, r)); 

     posts = posts.map((post, i) => { 
      if(posts[i].totalLikes) { 
       connection.then((conn) => { 
        return conn.query("SELECT u.userId, u.first, u.last FROM likes l JOIN posts p ON p.postId = l.postId JOIN users u ON u.userId = l.userId WHERE p.postId = ?", [post.postId]); 
       }).then((likesRows) => { 
        posts[i].likes = likesRows.map((r) => Object.assign({}, r)); 
       }); 
      } 
     }); 

     return posts; 

    }).then((posts) => { 
     console.log(posts); 
    }); 
}); 

回答

3

變化:

  1. 剛剛鏈中的映射一起
  2. 沒有必要使用i訪問時映射,因爲該項目已作爲第一個參數給出
  3. 既然你映射的承諾,您必須使用類似Promise.all的東西來解決它們
  4. 您已經解決connection.then,無需再次執行。您可以重複使用來自上方範圍的conn
  5. 也許你還可以提取對象複製到一個幫手乾淨的東西了進一步

下面的代碼:

const copyObject = o => Object.assign({}, o)); 
connection.then(conn => 
    conn 
    .query("SELECT userId, postId FROM posts") 
    .then(postRows => Promise.all(
     postRows 
     .map(copyObject) 
     .map((post) => { 
      const getLikes = post.totalLikes 
      ? conn.query("SELECT u.userId, u.first, u.last FROM likes l JOIN posts p ON p.postId = l.postId JOIN users u ON u.userId = l.userId WHERE p.postId = ?", [post.postId]) 
      : Promise.resolve([]); 
      return getLikes 
      .then(likesRows => { 
       post.likes = likesRows; 
       return post; 
      }); 
     }) 
    )) 
) 
.then(posts => { 
    console.log(posts); 
}) 
+0

感謝您的幫助。不承諾。所有的承諾?另外,你可以詳細解釋這個答案,因爲'conn'沒有在你提供的代碼片段中設置:/ – AnchovyLegend

+0

@AnchovyLegend增加了一個完整的例子。是的,'Promise.all'確實承諾了一系列的承諾。您必須在代碼中執行此操作的原因是您有一個數組映射,有時會返回一個承諾,有時不會,所以您可以在帖子沒有類似的情況下返回'Promise.resolve()'確保數組只包含承諾。否則,混合異步代碼和非異步代碼會導致很多問題,例如[Zalgo](http://blog.izs.me/post/59142742143/designing-apis-for-asynchrony) – nem035

+0

我欣賞所有信息和努力將這個響應放在一起,儘管使用上面的例子仍然不會將日誌記錄到控制檯。 – AnchovyLegend

1

地圖不改變它被調用的數組的值。在返回一個新的數組。我覺得你已經知道這一點,只是忘了補充一點。

posts = posts.map((post, i) => { 
      if(posts[i].totalLikes) { 
       connection.then((conn) => { 
        return conn.query("SELECT u.userId, u.first, u.last FROM likes l JOIN posts p ON p.postId = l.postId JOIN users u ON u.userId = l.userId WHERE p.postId = ?", [post.postId]); 
       }).then((likesRows) => { 
        posts[i].likes = likesRows.map((r) => Object.assign({}, r)); 
       }); 
      } 
     }); 
+1

問題也是嵌套的承諾。 – nem035

+0

你說得對。我也應該指出這一點。 – ThomasK

+0

@ThomasK,我欣賞這個建議,但是,這並沒有解決問題 - 目前得到一個不能設置屬性喜歡未定義的錯誤,我也懷疑嵌套承諾需要有點不同。 – AnchovyLegend