在ComponentDidMount()内部,我们定期调用api以获取数据。但是即使在组件卸载后,仍然会调用api。
async componentDidMount() {
let { getItemHistoryData } = this.props;
for (let i = 0; i < 25 && !this.props.is_synched; i++) {
await wait(5000);
getItemHistoryData();
}
}
const wait = (ms) => {
return new Promise(resolve => setTimeout(resolve, ms));
}
但是,即使用户移至另一个页面,也会调用getItemHistoryData()操作。
答案 0 :(得分:0)
我认为您需要重构一下代码...
您需要跟踪setTimeout
才能将其停在componentWillUnmount()
let t;
async componentDidMount() {
let { getItemHistoryData } = this.props;
t = setTimeout(getItemHistoryData(), 5000);
}
componentWillUnmount() {
clearTimeout(t);
t = null;
}
getItemHistoryData() {
// Do the function's stuff here
if(!this.props.is_synched){
t = setTimeout(getItemHistoryData(), 5000);
}
}
在i < 25 && !this.props.is_synched
末尾做关于getItemHistoryData()
的事情,然后再次调用-或不调用setTimeout
答案 1 :(得分:0)
componentDidMount运行并完成。但是它有一个Promise,当实现时,它将在Promise内部调用回调。这是由javascript引擎完成的。与反应无关。
编辑:看起来for循环确实被完全执行,但是在await
处阻塞。因此,它创建了一个承诺链,而不是一次创建25个承诺。需要做更多的研究。我虽然只有for-of循环能做到这一点。很抱歉提供错误信息。
这是您的代码转换为es5 Converted code with Babel JS
时的样子答案 2 :(得分:0)
我为您提供了更多我喜欢使用的选项
保存状态:
intervalId: null,
intervalCounter: 0
和componentDidMount添加:
const intervalId = setInterval(this.timer, 5000, 25)
创建一个新功能timer
:
timer = async () => {
if(this.state.intervalCounter <= 25){
getItemHistoryData();
this.setState({intervalCounter: this.state.intervalCounter + 1})
} else {
clearInterval(this.state.intervalId); //clear
}
}
并且不要忘记清除用户离开屏幕时的间隔:
componentWillUnmount() {
clearInterval(this.state.intervalId);
}
答案 3 :(得分:0)
从上面的代码中我了解到,即使卸载了组件,循环也一直运行到完成。为了解决这种特殊情况而无需在代码中进行重大更改,您可以使用布尔值来跟踪组件的卸载,并在循环条件中使用它来确保循环在卸载之后的迭代中退出。请注意,卸载组件后,此操作仍将执行挂起的任务。
async componentDidMount() {
let { getItemHistoryData } = this.props;
for (let i = 0; i < 25 && !this.props.is_synched && !this.isUnmounted; i++) {
await wait(5000);
getItemHistoryData();
}
}
async componentWillUnmount(){
this.isUnmounted = true;
}
如果要防止进一步的迭代,可以重构代码以使用 setInterval ,然后使用 clearInterval 进行清理。对于大多数实际情况,我上面建议的方法应足够并且可以防止代码重构。