我正在尝试调用200个远程资源以在我的表格中显示,同时显示一个进度条来显示剩余的调用次数。
使用这个示例来演示如何使用Fetch()和Promise.all()来调用setState()来更新新数据。
我的问题在于每个promise的.then(),它计算一些逻辑,然后调用setState()来更新数据。
我的进度条使用Object.keys(data).length来显示进度。
在Promise.all()触发“完成”状态后,移除进度条,promise本身仍然在调用它们的then(),这导致进度条在显示完所有已解决的promise之前就被隐藏了。
如何正确处理这个问题?
演示,使用setTimeout()来模拟昂贵的逻辑。
问题在于Promise.all.then: 20应该在Render 20之后。
Render 0 ... Render 12 Promise.all.then: 20 # 我需要这个在每个Render之后记录 Render 13 ... Render 19 Render 20
为了使演示显示出问题,进度条在完全填满之前就被移除(变成红色)。
const { useState } = React;
const Example = () => {
const [done, setDone] = useState(false);
const [data, setData] = useState({});
const demoData = Array.from(Array(20).keys());
const demoResolver = (x) => new Promise(res => setTimeout(() => res(x), Math.random() * 1250))
const loadData = () => {
const promises = demoData.map(c => demoResolver(c));
promises.forEach(promise => {
promise
.then(r => {
setTimeout(() => {
setData(p => ({ ...p, [r]: r }));
}, 500);
})
});
Promise.all(promises)
.then(r => {
console.log('Promise.all.then: ', r.length)
setDone(true);
})
}
console.log('Render', Object.keys(data).length);
const progressBarIsShownDebugColor = (done)
? 'is-danger'
: 'is-info';
return (
<section className='section'>
<h1 className='title is-3'>{'Example'}</h1>
<progress
max={demoData.length}
value={Object.keys(data).length}
className={'progress my-3 ' + progressBarIsShownDebugColor}
/>
<button onClick={loadData}>Start</button>
</section>
)
}
ReactDOM.render(<Example />, document.getElementById("react"));
.as-console-wrapper { max-height: 50px !important; }
<script src="https://cdnjs.cloudflare.com/ajax/libs/react/17.0.1/umd/react.production.min.js"></script> <script src="https://cdnjs.cloudflare.com/ajax/libs/react-dom/17.0.1/umd/react-dom.production.min.js"></script> <link rel="stylesheet" href="https://cdn.jsdelivr.net/npm/bulma@0.9.4/css/bulma.min.css"> <div id="react"></div>
Copyright 2014-2026 https://www.php.cn/ All Rights Reserved | php.cn | 湘ICP备2023035733号