vrt*_*515 2 javascript fetch reactjs 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}))
Run Code Online (Sandbox Code Playgroud)
返回promise数组的函数如下所示:
fetchMoreData(arr) {
const promises = arr.map(el => {
return fetch(someUrl)
.then(data => data.json())
.then(data => data)
})
return promises;
}
Run Code Online (Sandbox Code Playgroud)
我认为将Promise.all链接到另一个Promise不好,是否有推荐且更优雅的方式来实现此目的?
您说的方法不好是正确的,原因如下:
.then(data => {
const newData = [...data];
Promise.all(fetchMoreData(newData)).then(el => {
// more calculation
newData.push(el.someValue);
})
return newData;
})
Run Code Online (Sandbox Code Playgroud)
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);
}
Run Code Online (Sandbox Code Playgroud)
考虑到这一点,让我们继续两种解决方案:
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 });
});
Run Code Online (Sandbox Code Playgroud)
请注意,我们return fetchMoreData(array).then(...)在嵌套延续中也是如此return array。这将允许在下一个链中array传递给data。
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 });
});
Run Code Online (Sandbox Code Playgroud)
在这里,我们封装在另一个的依赖性Promise.all()和同时通过array并promise沿到下一个扁平链,我们然后使用阵列解构语法来在回调参数再次分离出来。从那里开始,我们执行其他计算,然后将数组传递到最终链。
| 归档时间: |
|
| 查看次数: |
132 次 |
| 最近记录: |