2017-04-04 5 views
1

J'ai 1 211 434 adresses IP qui ont dû être converties en géolocalisations. J'ai trouvé une API qui répond à cette question en utilisant la requête GET. Mais la chose est, lorsque vous utilisez une boucle for, je ne peux pas envoyer l'adresse IP et recevoir la description correctement.Noeud JS pour la boucle et la poussée de matrice

Majorly J'ai deux questions:

  1. Je ne peux pas sortir le tableau ip_and_info, et ne peut pas trouver la raison. Quelqu'un peut-il me dire ce qui s'est mal passé?

  2. Maintenant, le code que j'ai écrit peut récupérer toutes les informations dont j'ai besoin, il y a environ 200 adresses IP dans le test_ip.txt. Y aurait-il un problème potentiel si j'essaie d'envoyer toutes ces adresses IP 1M?

Est-ce que quelqu'un peut me donner un conseil?

Très appréciée.

Mon code est comme ci-dessous:

fs = require('fs') 
async = require("async") 
http = require('http') 

ip_and_info = [] 
// getIPInfo("1.171.58.24") 


fs.readFile("../test_ips.txt", "utf-8", (err, content, printArr) => { 

    content = content.split("\n") 

    async.each(content, (ip) => { 
     content = getIPInfo(ip) 
     // console.log(ip) 
    }, (err) => { 
     if (err) { 
      console.log(err) 
     } else { 
      console.log(ip_and_info) 
     } 
    }) 

    // for (i in content) { 
    //  ((ip) => { 
    //   getIPInfo(ip) 
    //  })(content[i]) 
    // } 


}); 



function getIPInfo(ipAddress) { 

    options = { 
     host: 'freegeoip.net', 
     path: '/csv/' + ipAddress 
    } 

    request = http.get(options, function(response) { 
     // console.log('STATUS: ' + response.statusCode) 
     // console.log('HEADERS: ' + JSON.stringify(response.headers)) 

     // Buffer the body entirely for processing as a whole. 
     bodyChunks = [] 
     response.on('data', function(chunk) { 

      bodyChunks.push(chunk) 

     }).on('end', function() { 

      body = Buffer.concat(bodyChunks) 
      content = body.toString('ascii') 
      ip_and_info.push(content) 
      console.log(content) 
      return content 

     }) 
    }) 

    request.on('error', function(e) { 
     console.log('ERROR: ' + e.message) 
    }) 
} 

PRÉCIEUSE!

+0

Ce n'est pas le problème, mais votre code est en proie à [* L'horreur de Implicite Globals *] (http://blog.niftysnippets.org/2008/03/horror-of-implicit-globals. html) * (c'est un post sur mon petit blog anémique) * - déclarez vos variables. –

+1

Vous avez besoin de promesses où vous poussez tout votre processus asynchrone dans le tableau et le résolvez ensemble –

+1

Votre code devrait imprimer juste des tableaux vides. C'est parce que votre boucle terminera son exécution avant même que getIPInfo() ne soit résolu. Comme l'a dit @VinodLouis, vous pouvez gérer cela avec l'aide de Promises. Si vous n'êtes pas à l'aise avec les promesses, faites le moi savoir. Je vais essayer de proposer une solution. –

Répondre

-1

Je pense que votre problème est peut-être que vous déclarez à nouveau la variable 'content' à chaque boucle que vous créez.

Alors peut-être changer la boucle à ceci afin de ne pas réinitialiser la variable chaque fois que la boucle s'exécute. Je souhaite que fixe votre problème:

IPList = content.split("\n") 

    async.each(IPList, (ip) => { 
     IPGeoLocation = getIPInfo(ip) 
     console.log(IPGeoLocation) 
    }, (err) => { 

Quant à faire avec un million d'adresses IP, je ne peux pas voir problème majeur aussi longtemps que vous avez une bonne quantité de mémoire sur votre ordinateur. Vous aimeriez peut-être ajouter un appel 'wait' afin de ne pas marteler le serveur de manière aussi cohérente. Ils pourraient vous bloquer! J'attendre 1 seconde entre chaque appel en ajoutant

sleep(1000); 

après avoir obtenu l'adresse IP.

1

Le problème se trouve dans cette ligne

content = getIPInfo(ip)

getIPInfo devrait être une fonction async. Une façon de le faire serait d'envoyer un rappel à la fonction et dans la fonction retourner la sortie dans le rappel.

async.each(content, getIPInfo, (err) => { 
    if (err) { 
     console.log(err) 
    } else { 
     console.log(ip_and_info) 
    } 
}) 

Et dans la fonction getIPInfo

function getIPInfo(ipAddress, callback) { 
    ..... 
    ..... 
    ip_and_info.push(content) 
    callback(); 
} 

En outre, au lieu d'utiliser async.eachSeries d'utilisation de async.each ou async.eachLimit sinon il essaiera d'envoyer la demande pour tous 1,211,434 ips.

0

Utiliser Promise. Utilisez les mots-clés let et const. Sérieusement, les globales implicites ne sont pas amusantes. Décidez s'il faut utiliser ' ou " et respectez-le, il est beaucoup plus lisible.

Avec Promise, inutile d'utiliser async ou votre variable ip_and_info.

'use strict'; 

const fs = require('fs'), 
    http = require('http'); 

fs.readFile('../test_ips.txt', 'utf-8', (err, content) => { 
    content = content.split('\n'); 

    Promise.resolve().then(() => { 
     return getAllIPInfo(content); 
    }).then((ipsInfos) => { 
     console.log('Info:' + ipsInfos); 
    }).catch((error) => { 
     console.error('Error: ' + error); 
    }); 
}); 

function getAllIPInfo(ipsAddress) { 
    return new Promise((resolve, reject) => { 
     let ipsInfo = []; 
     ipsAddress.reduce((previous, current, index, ips) => { 
      return previous.then(() => { 
       return getIPInfo(ips[index]).then((content) => { 
        ipsInfo.push(content); 
        return Promise.resolve(); 
       }); 
      }); 
     }, Promise.resolve()).then(() => { 
      resolve(ipsInfo); 
     }).catch((error) => { 
      reject(error); 
     }); 
    }); 
} 

function getIPInfo(ipAddress) { 
    return new Promise((resolve, reject) => { 
     let options = { 
      host: 'freegeoip.net', 
      path: '/csv/' + ipAddress 
     }; 

     http.get(options, function(response) { 
      // console.log('STATUS: ' + response.statusCode) 
      // console.log('HEADERS: ' + JSON.stringify(response.headers)) 

      // Buffer the body entirely for processing as a whole. 
      let bodyChunks = []; 

      response.on('data', function(chunk) { 
       bodyChunks.push(chunk); 
      }).on('end', function() { 
       let body = Buffer.concat(bodyChunks), 
        content = body.toString('ascii'); 

       resolve(content); 
      }); 
     }).on('error', function(e) { 
      console.log('ERROR: ' + e.message); 
      reject(e); 
     }); 
    }); 
} 
+0

cette solution enverra la demande pour tous les 1.211.434 ips ensemble. Mieux si vous créez des objets de promesse d'un morceau de ips et à la fin de passer au morceau suivant. –

+0

@GolakSarangi: Mise à jour pour appeler séquentiellement les ips – DrakaSAN