javascript - 链中提取和 Promise.all 的多个 API 调用

标签 javascript reactjs fetch es6-promise

我正在我的函数中进行 API 调用以获取一些数据。 然后我需要根据第一次调用的特定值对返回的每项数据进行多次 API 调用。我在渲染状态时遇到问题,从多个 promise 添加的值在渲染期间不存在。

到目前为止,我有这样的东西:

fetch(url)
.then(resp => resp.json())
.then(data => {
  //do some calculations and populate new array and return it
})
.then(data => {
   const newData = [...data];
   Promise.all(functionWhichReturnsArrayOfPromises).then(el => {
      // more calculation
      newData.push(el.someValue);
   })
   return newData;
})
.then(data => this.setState({data: data}))

返回 promise 数组的函数看起来像这样:

fetchMoreData(arr) {
   const promises = arr.map(el => {
      return fetch(someUrl)
      .then(data => data.json())
      .then(data => data)
   })
   return promises;
}

我认为我将 Promise.all 链接到另一个 promise 中并不好,有推荐的更优雅的方法吗?

最佳答案

你说你的方法不好是正确的,原因如下:

.then(data => {
   const newData = [...data];
   Promise.all(fetchMoreData(newData)).then(el => {
      // more calculation
      newData.push(el.someValue);
   })
   return newData;
})

return newData 发生在您到达 newData.push(el.someValue) 之前,并且由于它们引用相同的数组,这意味着您正在调用 setState () 并传递一个异步改变的数组,独立于组件重新呈现的时间。

本质上,您已经创建了一个竞争条件,这将使您的组件状态不确定,因为它基于 fetch() 操作是在 React 框架决定重新渲染之前或之后完成组件。


为了解决这个问题,我想到了两个选项,所以请选择对您而言更具可读性或与您的编码风格一致的选项,但首先让我们解决一个小的重构问题,使您的辅助函数更加规范。

异步函数应该更愿意将一个 promise 返回给一个数组,而不是一个 promise 数组:

fetchMoreData(arr) {
   const promises = arr.map(el =>
     fetch(someUrl)
       .then(res => res.json())
   );

   return Promise.all(promises);
}

考虑到这一点,让我们继续两个解决方案:

嵌套(并返回)依赖于先前作用域的 promise 链

fetch(url)
  .then(res => res.json())
  .then(data => {
    // do some calculations and populate new array and return it
  })
  .then(array => {
    // nest the promise chain
    return fetchMoreData(array).then(result => {
      // more calculations dependent on array from previous scope
      result.forEach(el => {
        array.push(el.someValue);
      });

      // pass array along
      return array;
    });
  })
  .then(data => {
    this.setState({ data });
  });

请注意,我们返回 fetchMoreData(array).then(...),并且在嵌套延续中,也返回数组。这将允许 array 传递到下一个链中的 data

通过扁平化的 promise 链传递来自先前作用域的依赖

fetch(url)
  .then(res => res.json())
  .then(data => {
    // do some calculations and populate new array and return it
  })
  .then(array => {
    const promise = fetchMoreData(array);
    // pass the dependency along
    return Promise.all([array, promise]);
  })
  // destructure dependencies
  .then(([array, result]) => {
    // more calculations dependent on array from previous scope
    result.forEach(el => {
      array.push(el.someValue);
    });

    // pass array along
    return array;
  })
  .then(data => {
    this.setState({ data });
  });

在这里,我们将依赖封装在另一个 Promise.all() 中,并将 arraypromise 传递到下一个扁平链,然后我们使用数组解构语法在回调参数中再次分离出来。从那里,我们执行额外的计算,然后将数组传递到最终链。

关于javascript - 链中提取和 Promise.all 的多个 API 调用,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/57979376/

相关文章:

javascript - 如何对受控输入进行去抖处理?

reactjs - 输入正在失去对钩子(Hook)更新的关注

javascript - 在 Javascript 中正确处理多个调用

javascript - vuepress 版本上的 "fetch is not defined"

ios - 如何从 AFNetworking ios 中的 block 中提取数据?

javascript - JavaScript 中的 document.unload 覆盖或链接最后一个定义?

javascript - setInterval() 的替代方法 - 在计算机锁定/在 Chrome 中执行其他操作时保持时间

javascript - d3js - 可排序组条形图

java - 从java执行javascript代码(使用eclipse)

javascript - React-router v4 可选参数