[nodejs] Faire des requêtes par lot, en parallèle et avec une pause

Requete par lot

Objectifs

Pouvoir Requêter en masse une API (jusqu'à 30 000 requêtes)

  • en faisant n requêtes en parallèle
  • en donnant la possibilité de créer des lots de requêtes
  • en donnant la possibilité de pouvoir pauser l'envoie des lots

Prérequis

  • nodejs
  • axios pour gérer les requêtes et l'asynchrone
  • async await pour gérer l'asynchrone

 

Le code

La vue

<div class="btn-container">
<a id="btn" class="waves-effect waves-light btn">Get all URLS</a>
</div>
<hr>

<div id="container"></div>

<pre id="result"></pre>

Le style

body {
  margin: 0;
  min-height: 100vh;
  background: #004d4d;
}
#container > div {
  width: 150px;
  margin: 10px;
  padding: 10px;
  line-height: 12px;
  background: #ededed;
  display: inline-block;
  border: 2px solid #fff;
  
  animation-name: fade-in;
	animation-fill-mode: both;
	animation-duration: .3s;
}
.teal {
  background: #008080;
}

.btn-container {
  margin: 10px;
}

.card-title {
 font-size: 14px !important; 
}

@keyframes fade-in {
  0% { opacity: 0; }
  100% { opacity: 1; }
}


Le js

Pré-requis:
- crée un package.json en local avec npm init
- installer axios avec npm install axios --save
- coder dans votre fichier nomdefichier.js
- tester le resultat dans le terminal avec `$ node nomdefichier.js`
- tester le resultat dans le navigateur en ouvrant celui-ci

// on importe axios
const axios = require('axios');

let AllDatas = [],
    AllDatasInError = [],
    urls = [],
    waitTime = 500, // the amount of time we wait between each batch of request
    start = 0,
    step = 2, // number of url we request
    position = 0,
    nbRequest = 12; // number of request 

AllDatas['total'] = 0; // total of data

let btn = document.getElementById('btn');

btn.addEventListener('click', function() {
  batchProcessing(urls);
});

function createUrl() {
    for (let i = 1; i <= nbRequest; i++) { urls.push(`https://jsonplaceholder.typicode.com/photos/${i}`); } } createUrl(); // timer const waitFor = (ms) => new Promise(r => setTimeout(r, ms));

// parallel REQUEST with AXIOS
async function getData(links) {
    try {
        const res = await axios.all(links.map(link => axios.get(link)));
        console.log('GetData Start time', new Date());
        return res;
    } catch (error) {
        console.log('------------------------------------------');
        console.log(error);
    }
}

//
async function batchProcessing(urls) {
    const len = urls.length / step;
    // let result = [];
    console.time('batchProcessing');
    console.log('batchProcessing Start time', new Date());

    // use of an interceptor to edit every response
    axios.interceptors.response.use(function (response) {
        // Do something with response data        
        let responseData = response.data;

        // const newVal = {};
        if (responseData.id) {
          responseData['position'] = `${position}/${len}`;
            // create html element
            addElement(responseData);
          
            AllDatas['total'] += 1;
            AllDatas.push(responseData);
        }
        
        console.log('responseData', responseData);
        return responseData;
    }, function (error) {
        // Do something with response error
        return Promise.reject(error);
    });
  
  
  // batch processing

    for(let index = 0; index < len; index ++) {
      var processingUrl  = urls.slice(start, start + step);
      start += step;
      position += 1;
    
      console.log('position', position + ' / ' + len);
      console.log('processingUrl',  processingUrl);
      
      // make the requests
      const res = await getData(processingUrl);
      
      AllDatas = AllDatas.concat(res);
      // break time
      await waitFor(waitTime);
    }
    
    // we are now done
    console.log('End timer', new Date());
    console.timeEnd('getData');
    // console.log('Final AllDatas', AllDatas);
  
  // document.querySelector('pre').innerHTML = AllDatas;
}



/******
RENDERING THE HTML
*****/

function addElement (data) { 
console.log('element added', data);
let mainDiv = document.getElementById("container"); 
let newDiv = document.createElement("div");

let newContent = `
<div class="card">
<div class="card-image">
<img src="${data.thumbnailUrl}">
<span class="card-title">
Element ${data.id} 
</span>
</div>
<div class="card-content">
<p>${data.title}. (batch ${data.position})</p>
</div>
<div class="card-action">
<a href="${data.url}">See the source</a>
</div>
</div>`;


// console.log('newContent', newContent);
newDiv.innerHTML = newContent; 
mainDiv.appendChild(newDiv); 
}

Mettre à jour NPM et gérer les versions de node.js

Node JS

Node.js est mis à jour très régulièrement. Il devient vite difficile de suivre et de garder les bonnes versions sur sa machine surtout si vous travailler avec différentes versions.

Installer Node.js

Si vous installer Node pour la première fois, vous pouvez l’installer depuis le site internet nodejs.org avec l’installateur proposé.

Node Js
Node Js

Installer, mettre à jour, désinstaller via le terminal

Si vous souhaitez l’installer via le terminal, il suffit d’utiliser Homebrew. Vous aurez aussi besoin d’avoir xCode à jour.

Mettre à jour Node

Mise à jour depuis le site nodejs.org

Il suffit de récupérer l’installateur et de le réinstaller….

Gérer plusieurs versions de Node.js

A un moment ou un autre vous aurez besoin de switcher entre les différentes versions de node. Pour le faire facilement il y a deux solution : Node version Manager (nvm) et n.

Node version manager (nvm)

https://github.com/creationix/nvm

NVM est un script bash permettant

  • d’installer multiple versions de node
  • mettre à jour vers la dernière version
  • choisir la version par défaut du système
  • lister toutes les versions de node sur le système

n

https://github.com/tj/n

n est gestionnaire de package similaire à nvm.

La grosse différence est qu’il faut déjà avoir node pour l’installer.

Ou alors cloner le dépot et faire un make install