0
votes

Comment pousser les données renvoyées par une promesse dans un tableau?

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");
});


2 commentaires

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 - bien sûr, le code devra être dans une fonction async ... ou simplement à l'intérieur (async () => {... tout le code de la boucle à tous les codes de filefile ...}) ();


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 ; dans la fermeture } d'A pour boucle


3 Réponses :


0
votes

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");
      });
    }
  })
};


5 commentaires

Bien sûr, cela ne garantira pas l'ordre des données dans Doc.Table 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 revient avant le résultat de i === 9 - il serait préférable de faire doc.table [I-1] = JSON 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; . 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 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 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 () est asynchrone tandis que attendre fsp.writefile () est synchrone, donc à nouveau obstruer l'exécution du code et le rendu de code



3
votes

Je suggérerais d'utiliser attendre de sorte que votre pour boucle sera en pause pour chaque itération: xxx

L'autre possibilité est Pour exécuter toutes les demandes en parallèle et utilisez promess.all () pour savoir quand ils sont tous terminés. Ils sont essentiels pour les deux solutions consiste à utiliser la promesse que récupération () revient au contrôle de la connaissance lorsque des choses sont effectuées.

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: xxx

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 mapconcurrent () décrit ici < / a>.


5 commentaires

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 () 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!



0
votes

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 xxx

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.


0 commentaires