【问题标题】:How to use async/await syntax with forEach loop in Javascript?如何在 Javascript 中将 async/await 语法与 forEach 循环一起使用?
【发布时间】:2018-04-09 06:53:03
【问题描述】:

我已经查看了几个关于使用 async/await 和 forEach 循环的问题,但似乎没有任何内容涵盖我的用户案例......我怎样才能让下面的代码工作?现在我收到以下错误:

await 是保留字

代码如下:

export const fetchUserBookmarks = ( bookmarksIDs ) => async ( dispatch, getState, api ) => {

    dispatch({
        type: 'IS_FETCHING_BOOKMARKS'
    });

    try {

        bookmarks = [];

        bookmarksIDs.forEach( bookmarkID => {
            const bookmark = await api.get( selectedPostByIdEP + bookmarkID ); 
            bookmarks.push( bookmark ); 
        }); 

        dispatch({
            type: 'HAS_FETCHED_BOOKMARKS', 
            payload: bookmarks
        });

    } catch( error ) {

        dispatch({
            type: 'FAILED_FETCHING_BOOKMARKS', 
            payload: error
        });

    }

}

【问题讨论】:

  • async 添加到forEach 循环中,bookmarksIDs.forEach(async bookmarkID => {...})
  • 当然,这会起作用,但不如预期的那样,例如,dispatch 将在任何内容被推送到书签之前被调用,无论您在 forEach 中做什么 - 请参阅 this answer

标签: javascript async-await


【解决方案1】:

首先,要使用await,您应该将函数声明为async。您已经使用外部函数这样做了,但没有使用内部函数。

更改将如下所示:

bookmarksIDs.forEach(async bookmarkID => {

其次,您可能想要并行运行这些 api 调用。

您可以将forEach 替换为map 调用,然后一起等待所有生成的承诺。

为此,您的代码应如下所示:

const bookmarks = await Promise.all(
  bookmarksIDs.map(bookmarkID => 
    api.get( selectedPostByIdEP + bookmarkID )
  )
); 

--

似乎如果bookmarks 没有在其他任何地方声明,就会导致问题。使用constlet 应该可以解决这个问题。

【讨论】:

  • 第一步与第二步的关系如何?
  • 第一点是显示代码中缺少的内容。第二点是展示如何修改代码以并行运行,如果这是您打算做的。
  • async 并没有丢失。把它放在那里根本行不通。
  • 你不能在没有它的内部使用await api.get。但我同意,这就是为什么我更喜欢答案第二部分中的解决方案。
  • @TalZ 操作在这里。我刚刚尝试了您的代码(第二部分),但它似乎对我不起作用。更准确地说,请求正在发出并且是成功的(我可以在检查员的网络选项卡中看到),但实际上Promise.all sn-p 后面的任何代码都不会执行。即使只是 console.log 也不会在控制台上打印任何内容...
【解决方案2】:

forEach 不是循环;它是您将函数传递给的函数。没有办法从中得到承诺。如果要一个一个地执行api.gets,可以使用for循环:

for (const bookmarkID of bookmarksIDs) {
    const bookmark = await api.get(selectedPostByIdEP + bookmarkID); 
    bookmarks.push(bookmark); 
}

如果您想并行执行它们,您可以创建多个 Promise 并使用 Promise.all 来收集它们的结果:

const bookmarks = await Promise.all(
    bookmarksIDs.map(
        bookmarkID => api.get(selectedPostByIdEP + bookmarkID)
    )
);

【讨论】:

    【解决方案3】:

    forEach 循环与 promise 和 async 函数不兼容。采用 for.. of 循环。它会工作得很好。

    async(data)=>{
        const ids = ["xyz","abc"]
        for (const id of ids){
        let data = await Collection.findById(id)
        console.log(data)
        } 
    }
    

    【讨论】:

      【解决方案4】:

      你会想做这样的事情

      try {
      
          bookmarks = await Promise.all(bookmarksIDs.map( bookmarkID => api.get( selectedPostByIdEP + bookmarkID )); 
      
          dispatch({
              type: 'HAS_FETCHED_BOOKMARKS', 
              payload: bookmarks
          });
      
      }
      

      【讨论】:

        猜你喜欢
        • 2022-06-23
        • 2020-09-24
        • 1970-01-01
        • 2021-02-27
        • 2022-01-13
        • 2018-08-04
        • 2014-03-13
        相关资源
        最近更新 更多