如何链接多个 fetch() 承诺?

新手上路,请多包涵

以下代码获取一个 json 列表,然后对每个列表项执行另一个获取调用以更改它们的值。问题是它不是同步完成的。 “new”在“update”之前打印到控制台。

 fetch(API_URL_DIARY)
.then(response => response.json())
.then(data => {
  console.log("old", data);
  return data;
})
.then(data => {
  data.forEach(function(e, index,array) {
    fetch(API_URL_FOOD_DETAILS + e.foodid)
    .then(response => response.json())
    .then(data => {
      array[index] = {...e, ...data};
      console.log("update");
    })
  });

  console.log("new", data)
});

更新

这是我合并@Andy 解决方案的方式:

 function fetchFoodDetails(id, index) {
  return fetch(API_URL_FOOD_DETAILS + id)
  .then(response => response.json())
  .then(data => {
      return [index, data];
  });
}

function fetchDiary() {
  return fetch(API_URL_DIARY)
  .then(response => response.json())
  .then(data => {
    return data;
  })
}

(async () => {
  const data = await fetchDiary();
  console.log("old", JSON.stringify(data));

  const promises = data.map((food, index) => fetchFoodDetails(food.id, index));
  await Promise.all(promises).then(responses => {
    responses.map(response => {
      data[response[0]] = {...data[response[0]], ...response[1]};
      console.log("update");
    })
  });
  console.log('new', JSON.stringify(data));
})();

这更困难,所以我选择了@connoraworden 的解决方案。但我认为它可以简化。

感谢您的所有回答。

原文由 Username 发布,翻译遵循 CC BY-SA 4.0 许可协议

阅读 478
2 个回答

解决此问题的最佳方法是使用 Promise.all()map()

map 在这种情况下会做什么,返回 fetch 的所有承诺。

然后会发生什么 await 将使您的代码执行同步,因为它会等待所有承诺在继续执行之前得到解决。

此处使用 forEach 的问题在于,它不会等待异步请求完成,然后才移至下一项。

您应该在此处使用的代码是:

 fetch(API_URL_DIARY)
    .then(response => response.json())
    .then(data => {
        console.log("old", data);
        return data;
    })
    .then(async data => {
        await Promise.all(data.map((e, index, array) => {
            return fetch(API_URL_FOOD_DETAILS + e.foodid)
                .then(response => response.json())
                .then(data => {
                    array[index] = {...e, ...data};
                    console.log("update");
                })
        }));

        console.log("new", data)
    });

原文由 connoraworden 发布,翻译遵循 CC BY-SA 4.0 许可协议

在单个数组中存储多个响应

下面的代码在查询中获取多个关键字,并将所有三个响应的所有响应存储到 all 数组

let queries = ["food", "movies", "news"]
let all = []

queries.forEach((keyword)=>{
  let [subres] = await Promise.all([fetch(`https://reddit.com/r/${keyword}/hot.json?limit=100`).then((response) => response.json())]);
  all.push(subres)
})

//now you can use the data globally or use the data to fetch more data
console.log(all)

原文由 Alohe 发布,翻译遵循 CC BY-SA 4.0 许可协议

撰写回答
你尚未登录,登录后可以
  • 和开发者交流问题的细节
  • 关注并接收问题和回答的更新提醒
  • 参与内容的编辑和改进,让解决方法与时俱进
推荐问题