J'essaie de passer 200 appels vers une ressource distante à afficher dans mon tableau, tout en affichant une barre de progression pour indiquer le nombre d'appels restants.
Utilisez cet exemple pour montrer comment utiliser Fetch()
et Promise.all()
/code> pour mettre à jour les nouvelles données.
Mon problème concerne le .then()
de chaque promesse, qui calcule une certaine logique puis appelle setState()
Ma barre de progression utilise Object.keys(data).length
Après que Promise.all()
déclenche l'état "Complet", supprimant la barre de progression, les promesses elles-mêmes appellent toujours leur then()
, ce qui entraîne le masquage de la barre de progression avant que toutes les promesses résolues ne soient affichées.
Comment résoudre correctement ce problème ?
Démo, utilisez setTimeout()
pour simuler une logique coûteuse.
Le problème est que Promise.all.then: 20
devrait être après Render 20
.
Rendu 0 ... Rendu 12 Promise.all.then : 20 # J'ai besoin que cela soit enregistré après chaque rendu Rendu 13 ... Rendu 19 Rendu 20 ≪/pré>Pour que la démo montre le problème, la barre de progression a été supprimée (devenue rouge) avant d'être complètement remplie.
const { useState } = React; const Exemple = () => { const [done, setDone] = useState(false); const [données, 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)); promesses.forEach(promesse => { promesse .then(r => { setTimeout(() => { setData(p => ({ ...p, [r]: r })); }, 500); }) }); Promesse.tout(promesses) .then(r => { console.log('Promise.all.then:', r.length) setDone(vrai); }) } console.log('Render', Object.keys(data).length); const progressBarIsShownDebugColor = (fait) ? 'est-danger' : 'est-info'; retour () } ReactDOM.render( {'Exemple'}
, document.getElementById("react")); .as-console-wrapper { hauteur maximale : 50px !important; }
Le problème montré dans le code ci-dessus est qu'après avoir obtenu les données, il y a un délai asynchrone supplémentaire de 500 ms avant de définir l'état. Dans le code réel, il semble qu'il y ait un traitement supplémentaire (probablement synchrone) qui provoque l'appel de
setData
在.all
.La meilleure chose à faire est de rendre
done
作为一个计算属性而不是一个单独的状态,因为在那个点上,您不需要依赖于状态设置竞争,并且Object.keys(data).length
suffisamment bon marché pour ne pas dégrader les performances (et vous l'utilisez dans d'autres domaines, si cela devient un problème, vous pouvez le mettre en cache dans une variable).