javascript - 如何使用 Promise.all 为 React 应用程序正确获取数据
问题描述
我正在开发一个 React 应用程序,我需要在组件安装时获取一些数据。由于我需要进行 3 次不同的调用,我认为最好使用 Promise.all 以并行方式进行。此处的代码工作得很好,它完全符合我的意图,但是,修改代码的人将其标记为错误,并带有消息“你没有在这里返回承诺。等待或承诺,但不是两者兼而有之”。我真的不明白他这话是什么意思。我只是一个初学者,他比我有更多的经验,所以我认为他是对的,这段代码是错误的,但我就是不知道为什么。
async componentDidMount() {
const start = Date.now();
// TODO: BUG! you are not returning the promise here! Either await or promise but not both!
const promises = [this.fetchReports({}), this.fetchEntities(), this.fetchCodePulseRange()];
await Promise.all(promises);
console.log("Data fetching time: ", Date.now() - start)
this.setState({ inited: true });
}
async fetchEntities() {
const res = await insightService.fetchEntities(this.props.profile.organisationId);
this.setState({ allEntities: res, entityType: 'product' });
}
async fetchReports(entities: { [key: string]: string }) {
const res = await insightService.fetchInsights(reports, entities, this.props.profile.organisationId, JSON.stringify(entities));
this.setState({ reportsWithData: res });
}
async fetchCodePulseRange() {
const res = await insightService.fetchCodePulseRange(this.props.profile.organisationId);
this.setState({ codePulseRange: res });
}
解决方案
你最好的办法是问这个人他们的意思。我看不出你将承诺放在一个数组中然后await
ing有任何问题,Promise.all
这样你就知道它们什么时候都已经实现了(或者其中一个被拒绝了)。Promise.all
即使在函数中,审阅者也可能并不完全清楚它的作用和原因async
(正是因为您指定的原因:开始操作,然后等待它们全部完成,允许它们并行运行) .
存在一个问题,即您的代码中没有任何内容可以处理或报告来自 fetch 操作的错误。这可能是他们试图在某种程度上间接表明的。Promise 的规则之一是:要么处理错误,要么将 Promise 链传播到将要发生的事情。React 不会处理来自 的承诺拒绝componentDidMount
,因此您需要自己处理错误。
我还将修改他的代码,以便您只进行一次状态更改而不是其中的四个:
componentDidMount() {
const start = Date.now();
const promises = [this.fetchReports({}), this.fetchEntities(), this.fetchCodePulseRange()];
Promise.all(promises)
.then(([reportsWithData, allEntities, codePulseRange]) => {
console.log("Data fetching time: ", Date.now() - start)
this.setState({
reportsWithData,
allEntities,
entityType: "product",
codePulseRange,
inited: true,
});
})
.catch(error => {
// ...handle/report error...
});
this.setState({ inited: true });
}
fetchEntities() {
return insightService.fetchEntities(this.props.profile.organisationId);
}
fetchReports(entities: { [key: string]: string }) {
return insightService.fetchInsights(reports, entities, this.props.profile.organisationId, JSON.stringify(entities));
}
fetchCodePulseRange() {
return insightService.fetchCodePulseRange(this.props.profile.organisationId);
}
但是如果你想保持增量更新(四个独立的状态更新),你可以这样做,只要确保处理错误,无论是在使用这些操作的componentDidMount
地方还是在其他任何地方。fetchXyz
例如,如果您不理会这些fetchXyz
操作,则:
componentDidMount() {
const start = Date.now();
const promises = [this.fetchReports({}), this.fetchEntities(), this.fetchCodePulseRange()];
Promise.all(promises)
.then(() => {
console.log("Data fetching time: ", Date.now() - start)
this.setState({ inited: true });
})
.catch(error => {
// ...handle/report error...
});
}
或者
async componentDidMount() {
const start = Date.now();
try {
const promises = [this.fetchReports({}), this.fetchEntities(), this.fetchCodePulseRange()];
await Promise.all(promises);
console.log("Data fetching time: ", Date.now() - start)
this.setState({ inited: true });
} catch (error) {
// ...handle/report error...
}
}
我不得不承认,我并不热衷于将承诺传递给不期望它们的事物(例如 React 代码调用componentDidMount
),但这是一种相对较小的风格,我不会像在回馈。
推荐阅读
- node.js - 使用请求模块 HTTP GET Firebase 函数 Node.js
- python - 如何将字符串与bs4对象进行比较
- fortran - 不同长度的Fortran子串比较问题
- entity-framework - 如何从现有的 sql server DB 生成模型类
- javascript - 如何使用画布从视频中解析图像数据而不将画布附加到页面?
- google-chrome - 在 Mac 上的 Google 表格中显示“开发者工具”
- c - 按下两个按钮时试图让电机停止
- javafx - 翻译节点后布局 x 和 y 保持不变
- c# - 带有 IIS 502.5 错误的 net 核心应用程序
- cmake - 如何为 _existing_ 库创建目标?