Je fais un appel à Udemy API. Pour faire des appels simultanés, j'utilise une boucle. Ce faisant, j'y incrémente automatiquement les numéros de page et essaye de récupérer les données de chaque page et de le stocker dans une matrice afin que je puisse écrire toutes les données dans un seul fichier au format JSON. Mais tout ce que je reçois, c'est un tableau vide. Comment accéder à la valeur renvoyée par la promesse et stockez-vous dans le tableau Doc.Table?
Mon code: P>
const fetch=require("node-fetch"); const fs=require("fs"); let doc={}; doc.table=[]; for(let i=1;i<=10;i++){ fetch('https://www.udemy.com/api-2.0/courses/ page='+i+'&page_size=10&client_id=${client_id}&client_secret=${client_secret},{ method:'GET', body:null, headers:{authorization: ${auth_code}} }) .then(res=>res.json()) .then(json=>doc.table.push(json)) }; fs.writeFile("UDEMY.json",JSON.stringify(doc),function(err){ if(err) throw err; console.log("Complete"); });
3 Réponses :
Vous pouvez essayer de vérifier l'index de la boucle actuelle et d'écrire votre fichier dans la dernière promesse Fullroudment:
const fetch = require('node-fetch'); const fs = require('fs'); let url; let counter = 10; const doc = { table: [] }; for (let i = 1; i <= 10; i++) { url = `https://www.udemy.com/api-2.0/courses/page=${i}&page_size=10&client_id=${client_id}&client_secret=${client_secret}`; fetch(url, { method: 'GET', body: null, headers: { authorization: auth_code } }) .then(res => res.json()) .then(json => { // next line will not guarantee the order of pages // doc.table.push(json); // so we can use current loop index and counter doc.table[i] = json; // when counter is 0 we can write a file if (!--counter) { fs.writeFile('UDEMY.json', JSON.stringify(doc), function(err) { if (err) { throw err; } console.log("Complete"); }); } }) };
Bien sûr, cela ne garantira pas l'ordre des données dans Doc.Table CODE> ne garantira pas non plus que toutes les données sont présentes, car lorsque je === 9, cela peut prendre si longtemps que le résultat de
i === 10 code> revient avant le résultat de
i === 9 code> - il serait préférable de faire
doc.table [I-1] = JSON code> et ont également un compteur de résultats (Impossible d'utiliser la longueur de la matrice ici non plus) et de continuer une fois que 10 résultats ont été reçus
À l'ordre de l'extrémité de code OP, l'ordre d'extraction n'a été enregistré de toute façon pas, si la commande est importante, nous pouvons utiliser doc.table [i] = json; code>. Je mettrai à jour ma réponse, merci de pointer ...
Je pense que l'OP ne comprend pas les chaînes de promesse, il pensait que tout cela a été fait après la boucle pour la boucle, pensait donc que chaque boucle serait faite en série, plutôt que parallèle: p
@ jfriend00 ouais. Gardera cela à l'esprit. Merci pour le conseil!
JCFIDE00, merci pour vos commentaires supprimés (à partir de 2 heures) sur Antipaterns de ma réponse. Il n'y a rien de mal à garder l'extraction asynchrone d'appels code> appelle asynchrone et exécuter le rappel nécessaire de manière asynchrone uniquement lorsque la condition est satisfaite. De cette façon, le rendu n'est pas bloqué. Si nous convertissons 10 appels asynchrones
extraire code> appels sur synchrones, le rendu de navigateur et les autres opérations JS planifiées seront bloquées jusqu'à ce que tous les 10 appels réussissent ou échouent. Aussi
fs.writefile () code> est asynchrone tandis que
attendre fsp.writefile () code> est synchrone, donc à nouveau obstruer l'exécution du code et le rendu de code
Je suggérerais d'utiliser L'autre possibilité est Pour exécuter toutes les demandes en parallèle et utilisez Si vous voulez vraiment les exécuter en parallèle et vous voulez Assurez-vous que votre hôte cible le permettra, vous pouvez le faire: p> et, si vous voulez un niveau de requêtes parallèles, mais que vous voulez limiter le nombre de personnes en parallèle, Vous pouvez utiliser attendre code> de sorte que votre
pour code> boucle sera en pause pour chaque itération:
promess.all () code> pour savoir quand ils sont tous terminés. Ils sont essentiels pour les deux solutions consiste à utiliser la promesse que
récupération () code> revient au contrôle de la connaissance lorsque des choses sont effectuées. P>
mapconcurrent () code> décrit ici < / a>. p> p>
Certaines API ne voudraient pas trop de demandes parallèles de toute façon, il est probablement préférable de les faire en série (je pense que l'OP pensait qu'ils fonctionnaient en série de toute façon)
@ Nishanthb.s - Comme je l'ai dit, vous pouvez exécuter vos demandes en parallèle si vous souhaitez utiliser promess.all () code> et avoir une conception beaucoup plus propre. Certains hôtes ne vous permettront pas de démarrer 100 demandes parallèles (vous obtiendrez de tarification limitée, ou de planter l'hôte ou de faire fonctionner vraiment l'hôte, vraiment inefficacement).
@ Nishanthb.s - J'ai ajouté une option parallèle à l'aide de promesses pour gérer le flux de contrôle.
@ Nishanthb.s - Notez également que ces deux options vous offrent une manipulation d'erreur propre dans un endroit central. C'est un autre avantage d'utiliser de bons modèles de design avec des promesses.
@ jfriend00 ouais je l'ai eu !. Dans votre code précédent utilisant ASYNC Await, bien que le délai d'exécution soit retardé, aucune donnée n'a été perdue lors de la rédaction du fichier. Je pense que c'est plus important. Merci pour votre réponse!
Vous pouvez également enregistrer les promesses dans un tableau et y accéder une fois que chacun d'entre eux est rempli si la commande est importante les données seront désormais un tableau contenant les résultats des promesses individuelles . Vous pouvez les fusionner ou les traiter comme content.
Sachez que la fonction ci-dessus ne résout qu'une fois que toutes les promesses précédentes sont résolues. P> p>
Comme les promesses sont asynchrones, vous devrez attendre qu'ils résolvent avant d'utiliser tout résultat - le moyen le plus simple consiste à utiliser async / attendre et attendre le
Fetch code> - bien sûr, le code devra être dans une fonction
async code> ... ou simplement à l'intérieur
(async () => {... tout le code de la boucle à tous les codes de filefile ...}) (); code>
Deux choses de note dans le code que vous avez posté ... Vous semblez vouloir utiliser une chaîne de modèle, mais ne le faites pas correctement, et pas besoin de
; code> dans la fermeture
} code> d'A pour boucle