Le titre réécrit est : Appel de React Promise.all().then() avant que chaque setState de promise.then() ne soit rendu
P粉162773626
P粉162773626 2023-08-20 11:02:53
0
1
328

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 ( 

{'Exemple'}

) } ReactDOM.render(, document.getElementById("react"));
.as-console-wrapper { hauteur maximale : 50px !important; } 
   


P粉162773626
P粉162773626

répondre à tous (1)
P粉426780515

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 desetData.all.

La meilleure chose à faire est de rendredone作为一个计算属性而不是一个单独的状态,因为在那个点上,您不需要依赖于状态设置竞争,并且Object.keys(data).lengthsuffisamment 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).

const [data, setData] = useState({}); const done = Object.keys(data).length === 20; // 在实际代码中为200

const { useState } = React; const Example = () => { const [data, setData] = useState({}); const done = Object.keys(data).length === 20; // 在实际代码中为200 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); }) }); } console.log('Render', Object.keys(data).length); const progressBarIsShownDebugColor = (done) ? 'is-danger' : 'is-info'; return ( 

{'Example'}

) } ReactDOM.render(, document.getElementById("react"));
.as-console-wrapper { max-height: 50px !important; }
   
    Derniers téléchargements
    Plus>
    effets Web
    Code source du site Web
    Matériel du site Web
    Modèle frontal
    À propos de nous Clause de non-responsabilité Sitemap
    Site Web PHP chinois:Formation PHP en ligne sur le bien-être public,Aidez les apprenants PHP à grandir rapidement!