Aller au contenu

parallélisation des taches nodejs


GROS_FAIGNAN

Messages recommandés

bonjour, je dispose d’un tableau d’objets js construit comme suis [{link:'https://some_url',text:"..."}].

je cherche a validé les url afin de :

  1. vérifier que je dispose bien de l’url finale et si nécessaire la mettre a jour,
  2. supprimer du tableau les objets dont l’url finale est sans intérêt (celle dont le status code !=200, principalement)

pour ce faire j’utilise 2 petites fonctions :

async function validateURL(array) {
    for (let elm of array) {
        let finalURL = await terminalURL(elm.link);

        if (typeof finalURL == 'string') {
            elm.link = finalURL;
        } else {
            array = array.filter(el => el.link != elm.link)
        }
    }
    console.log(array);
    return array;
}

async function terminalURL(url) {
    return new Promise((resolve, reject) => {
        axios({
            method: 'get',
            url: url,
            responseType: 'stream'
        }).then((response) => {
            if (response.data.responseUrl) {
                resolve(response.data.responseUrl);
            }
        }).catch(function(error) {
            reject(error.status);
        });
    }).catch((err) => {
        return ('some error');
    });
}
 

ces fonction semble faire le job que j’attend, par contre je ne suis pas sur que mon code soit bien optimiser.

De plus, de la façon dont j’ai structuré mon code, le traitement des url se fait de manière séquentielle, hors je souhaiterai que ce traitement ce fasse de manière parallèles. je m’explique :
L’appel à la fonction validateURL fait appel à la fonction terminalURL à qui elle passe l’url à contrôlé en paramètre.
En retour elle attend (await) de la fonction terminalURL l'url finale et modifie les valeurs de l’objet en fonction des résultats.

Ce que je souhaiterai serait que la boucle for...of de la fonction validateURL lance mes différentes requêtes Axios en parallèle sans attendre les résultats de retour.
Et que, d’un autre coté, dés qu’une valeur est disponible, elle déclenche un évènement qui mette mon objet a jour.

de quel coté dois je cherché ?

 
 
 
 
 
 
Modifié par GROS_FAIGNAN
Lien vers le commentaire
Partager sur d’autres sites

Bonjour,

Si je comprends bien ton code, ta fonction "validateUrl" doit retourner le tableau d'url validés.

Première remarque, le nom de la fonction n'est pas cohérent. Il prend en entrée un tableau d'URL mais le nom suggère qu'il ne peut en valider qu'une seule. Elle devrait plutôt s’appeler validateUrls (avec un s à la fin).
Ensuite, le mot "validate" suggère qu'elle retourne un statut de validation. Donc un booléen. Or elle retourne la liste des URLs qui ont été validées. Donc le nom final de la fonction devrait plutôt être:
getValidatedUrls, ou quelque chose dans le genre.

La fonction terminalUrl a le même problème de nommage que l'autre fonction.
Si je comprends bien ce qu'elle fait, elle envoie une requête http à l'url passée en paramètre et récupère une autre url qui se trouve dans le body. Donc son nom devrait plutôt être quelque chose du genre:
getTerminalUrlOf(url)

Ensuite pour ton problème, une solution serait de collecter l'ensemble des Promises dans un tableau et faire un Promise.all de ce tableau. Voir ici : https://developer.mozilla.org/fr/docs/Web/JavaScript/Reference/Global_Objects/Promise/all

donc en clair, le code final devrait ressemble à quelque chose qui ressemble à ça :

async function getValidatedURLs(array) {
  
  // On transforme chaque élément de la liste en sa promise associée
  const promises = array.map(elm => {
    return this.getTerminalURL(elm).then(terminalUrl => {
      elm.link = terminalUrl;
      return elm;
    });
  });
  
  // On résout toutes les promises parallèlement. Promise.all est fait pour ça.
  // Si jamais  getTerminalUrl rencontre une erreur, on renvoie null ce qui nous permettra de filtrer ensuite
  return Promise.all(promises.map(element => element.catch(_ => null)))
  // Quand on a obtenu tous les resultat, on retourne la liste de tous les elements retournés sans les nulls.
    .then(results => results.filter(element => element != null));
  
  // Le résultat final sera donc une promise (fonction async) d'un tableau contenant les elements dont on a réussi à récupérer "l'url terminale".
}

async function getTerminalURL(elm) {
  // Axios lui même retourne une promise donc pas besoin de wrapper le tout dans une autre Promise faite maison.
  return axios({
    method: 'get',
    url: elm.link,
    responseType: 'stream'
  }).then((response) => response.data.responseUrl);
}

En espérant avoir été assez clair.
Toutes mes excuses si des erreurs se sont glissés dans ma réponse, le vendredi à 18h30, je n'ai plus parfaitement les yeux en face des trous.

 

Modifié par Metz Bove
Lien vers le commentaire
Partager sur d’autres sites

Rejoindre la conversation

Vous pouvez publier maintenant et vous inscrire plus tard. Si vous avez un compte, connectez-vous maintenant pour publier avec votre compte.

Invité
Répondre à ce sujet…

×   Collé en tant que texte enrichi.   Coller en tant que texte brut à la place

  Seulement 75 émoticônes maximum sont autorisées.

×   Votre lien a été automatiquement intégré.   Afficher plutôt comme un lien

×   Votre contenu précédent a été rétabli.   Vider l’éditeur

×   Vous ne pouvez pas directement coller des images. Envoyez-les depuis votre ordinateur ou insérez-les depuis une URL.

×
×
  • Créer...