J'ai 2 onglets sur la page qui montre des visualisations générées à partir de différentes sources de données. Les deux visualisations nécessitaient plusieurs requêtes en arrière-plan pour récupérer les données avant de les rendre, il faut donc un certain temps pour que chaque onglet se charge individuellement. Actuellement, componentDidMount ressemble à ci-dessous:
async loadDataA(){
const { queries } = this.state;
queries.forEach((query) => {
a_query({query}).then(result => this.handleAResult(result));
});
}
async loadDataB(){
const { scopes, queries } = this.state;
queries.forEach(query => {
scopes.forEach(scope => {
b_query({scope, query}).then(result => this.handleBResult(result));
});
});
}
Bien que cela fonctionne, il ne commencera pas à charger les données pour B tant que le chargement des données pour A ne sera pas terminé. Si j'inverse l'ordre dans le componentDidMount comme ceci:
componentDidMount(){
this.loadDataB();
this.loadDataA();
}
puis il charge d'abord les données pour B, puis A.
Existe-t-il un moyen de charger les deux données simultanément?
(Je suis assez nouveau pour réagir, alors faites-le moi savoir si je manque quelque chose)
EDIT 1 Voici les fonctions de chargement des données:
componentDidMount(){
this.loadDataA();
this.loadDataB();
}
EDIT 2 La séquence d'exécution lorsque console.log été ajouté (merci @TKoL), lorsque A est appelé en premier, puis B:
Remarque: si vous avez besoin de connaître une autre partie du code, veuillez demander.
3 Réponses :
Vous voudrez rendre loadDataA et loadDataB asynchrones, en utilisant les promesses: https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Promise
Voici un exemple utilisant le sucre syntaxique async :
const loadDataA = async () => {
// Actual load logic goes here
}
En lisant tout jusqu'à présent, il semble que b_query soit terminé après a_query ou vice versa selon l'ordre d'appel. Donc, soit ils ont une logique qui provoque le séquençage, soit le côté serveur lui-même séquence les demandes (oui, il existe des fonctionnalités de serveur qui le font).
Modifier 1
Une troisième possibilité est que le point de terminaison que vous appelez se termine en premier et que la réponse soit renvoyée plus rapidement en déclenchant le. .then avant la fin du deuxième appel (merci @TKoL).
Il y a une troisième option que vous n'avez pas mentionnée: il est tout à fait possible que, pour des raisons tout à fait normales et attendues, les demandes que vous appelez en premier se terminent également en premier. Je crois qu'il interprète cette coïncidence comme "les demandes B attendent que les demandes A se terminent", alors qu'en réalité c'est juste "j'ai appelé les demandes B un peu plus tard, et elles ont fini un peu plus tard"
Ce n'est pas exactement le cas, donc en temps réel, les requêtes B prennent plus de temps à se charger que les requêtes A. Donc, si vous avez une séquence comme A puis B, alors cette théorie a un support, mais lorsque vous avez B puis A à ce moment-là, elle ne commencera même pas à rendre les valeurs A tant que toutes les valeurs B ne seront pas terminées. Je pense que cela pourrait être dû à l'application New Relic j'utilise pour obtenir les données. Mais j'enquête toujours et je mettrai à jour ici si j'ai trouvé le coupable.
Donc, vous avez votre code de chargement:
async loadDataA(){
const { queries } = this.state;
queries.forEach((query, index) => {
console.log('starting queryA ' + index);
a_query({query}).then(result => {
console.log('finishing queryA ' + index);
this.handleAResult(result)
});
});
}
async loadDataB(){
const { scopes, queries } = this.state;
queries.forEach((query, qi) => {
scopes.forEach((scope, si) => {
console.log('starting queryB ' + qi + ':' + si);
b_query({scope, query}).then(result => {
console.log('finishing queryB ' + qi + ':' + si);
this.handleBResult(result);
});
});
});
}
et vous l'appelez comme ceci:
this.loadDataA(); this.loadDataB();
Maintenant, c'est ma théorie selon laquelle cela fonctionne parfaitement bien. La façon dont votre code DEVRAIT fonctionner hypothétiquement, sans le changer du tout, est qu'il a appelé a_query_1, puis a_query_2, puis a_query ... z, et puis il fait toutes les b_queries, mais sans attendre qu'il obtienne les résultats des a_queries retour
Je recommanderais donc d'ajouter ces lignes console.log pour vérifier:
async loadDataA(){
const { queries } = this.state;
queries.forEach((query) => {
a_query({query}).then(result => this.handleAResult(result));
});
}
async loadDataB(){
const { scopes, queries } = this.state;
queries.forEach(query => {
scopes.forEach(scope => {
b_query({scope, query}).then(result => this.handleBResult(result));
});
});
}
Vous devriez voir TOUS les starting d' abord les journaux, A, puis les B, et alors vous devriez commencer à voir les finishing des journaux qu'ils commencent à la finition. Cela devrait vérifier que A et B fonctionnent "en même temps", dans le sens où les demandes B n'attendent pas que les demandes A se terminent avant que les demandes B ne commencent.
J'ai vu le montage. Cela signifie, pour autant que je sache, que tout fonctionne comme prévu et que vous n'avez rien à craindre.
J'ai lu un autre article de votre part qui dit que les requêtes B prennent beaucoup plus de temps que les requêtes A, donc même si les requêtes B se produisent en premier, les requêtes A doivent toujours se terminer en premier. Sachez simplement que, quelle que soit la manière dont vous effectuez les requêtes dans javascript, le javascript ne contrôle pas la manière dont votre serveur gère les requêtes. Si votre serveur traite des demandes antérieures avant de commencer à traiter des demandes ultérieures, aucune quantité de Javascript ne peut résoudre ce problème. C'est un problème côté serveur.
si
loadDataAetloadDataBchargent tous les deux des données de manière asyncronale, ils le feront déjà en même temps comme vous l'avez écrit. Si les données ne sont pas chargées de manière asynchrone, il n'y a aucun moyen de les faire en même tempsDonc, je suppose que la question est de savoir à partir de quoi chargez-vous les données et comment?
Oui, les données sont chargées pour les deux de manière asynchrone. Les données sont chargées à partir de différentes sources sans chevauchement. Pourtant, en fonction de la position des fonctions, il s'exécute de manière séquentielle. De plus, j'ai observé que si je
console.logdans les deux fonctions, il les imprime immédiatement. Mais le chargement des données pour une fonction ultérieure ne démarre pas tant que le premier n'est pas terminé. Est-ce que je manque quelque chose ici?Comment savez-vous que la demande de données
Bne démarre pas tant queAn'est pas terminé? au lieu de finir juste après?Sans voir le code spécifique qui charge les données, c'est difficile à dire
Ajout
loadDatacodeloadDatapour les deux fonctions.