我正在我的函数中进行 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()
中,并将 array
和 promise
传递到下一个扁平链,然后我们使用数组解构语法在回调参数中再次分离出来。从那里,我们执行额外的计算,然后将数组传递到最终链。
关于javascript - 链中提取和 Promise.all 的多个 API 调用,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/57979376/