Jump to content

parallélisation des taches nodejs


Recommended Posts

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é ?

 
 
 
 
 
 
Edited by GROS_FAIGNAN
Link to comment
Share on other 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.

 

Edited by Metz Bove
Link to comment
Share on other sites

Join the conversation

You can post now and register later. If you have an account, sign in now to post with your account.

Guest
Reply to this topic...

×   Pasted as rich text.   Paste as plain text instead

  Only 75 emoji are allowed.

×   Your link has been automatically embedded.   Display as a link instead

×   Your previous content has been restored.   Clear editor

×   You cannot paste images directly. Upload or insert images from URL.

 Share

×
×
  • Create New...