2016-05-17 7 views
0

Ich versuche, einige URLs asynchron aufzurufen und die Ergebnisse zu sammeln. Ich habe es mit "Promises" gemacht. Jetzt versuche ich meinen Kopf um async.js zu wickeln. Hierasync.each wird den Rückruf nicht ausführen

ist ein Code snipped:

var request = require("request"), 
    cheerio = require("cheerio"); 
    // base_url = "http://de.indeed.com/Jobs?q="; // after equal sign for instance: sinatra&l= 
var async = require('async'); 

/* search syntax: 
    - http://de.indeed.com/Jobs?q=node&l=berlin&radius=100 
*/ 

var search_words = ["django", "python", "flask", 
        "rails", "ruby", 
        "node", "javascript", "angularjs", "react", "express", "meteor", 
        "java", "grails", "groovy", 
        "php", "symfony", "laravel" ]; 


var base_url = "http://de.indeed.com/Jobs?q="; 
var stats = []; 


async.each(search_words, function(keyword) { 
    var url = base_url + keyword + "&l="; 
    request(base_url + keyword + "&l=", function(err, resp, body) { 
     if (err) throw err; 
     $ = cheerio.load(body); 
     num_str = $("#searchCount")[0].children[0].data.split(" ").reverse()[0]; 
     num_str = num_str.replace(/\./, ""); 
     num_str = num_str.replace(/,/, ""); 

     stats.push([keyword, num_str]); 
    }); 
}, function(err) { 
    if (err) throw err; 
    console.log(stats); 
}); 

Nach this kann ich eine Callback-Funktion als letztes Argument übergeben async.each das wird ausgelöst, wenn die Array verarbeitet wurde.

In meinem Fall wird der Rückruf nie ausgelöst scheint es.

Btw: Trevor Burnham erwähnt in seinem Buch "Async Javascript" die Funktion asyn.forEach Es scheint, das wurde aus async.js entfernt?


@robertklep gab mir einen Tipp einen Rückruf an die iteratee Funktion hinzuzufügen. // Dies ist die Arbeitsversion:

var request = require("request"), 
    cheerio = require("cheerio"); 
    // base_url = "http://de.indeed.com/Jobs?q="; // after equal sign for instance: sinatra&l= 
var async = require('async'); 

/* search syntax: 
    - http://de.indeed.com/Jobs?q=node&l=berlin&radius=100 
*/ 

var search_words = ["django", "python", "flask", 
        "rails", "ruby", 
        "node", "javascript", "angularjs", "react", "express", "meteor", 
        "java", "grails", "groovy", 
        "php", "symfony", "laravel" ]; 


var base_url = "http://de.indeed.com/Jobs?q="; 
var stats = []; 

async.each(search_words, function(keyword, callback) { 
    var url = base_url + keyword + "&l="; 
    request(url, function(err, resp, body) { 
     if (err) { 
      callback("ERROR in request"); 
     } else { 
      $ = cheerio.load(body); 
      num_str = $("#searchCount")[0].children[0].data.split(" ").reverse()[0]; 
      num_str = num_str.replace(/\./, ""); 
      num_str = num_str.replace(/,/, ""); 
      num = parseInt(num_str); 

      stats.push([keyword, num]); 
      callback(); 
     } 
    }); 
}, function(err) { 
    if(err) { 
     console.log(err); 
    } else { 
     stats_sorted = stats.sort(function(a, b) { 
      return b[1] - a[1]; 
     }); 
     console.log(stats_sorted); 
    } 
}); 

Antwort

0

Sie den Teil verpasst, wo die iteratee zwei Argumente bekommt: das Element und ein Rückruf. Dieser Callback muss aufgerufen werden, wenn die iteratee abgeschlossen ist (oder wenn ein Fehler aufgetreten ist):

async.each(search_words, function(keyword, callback) { 
    var url = base_url + keyword + "&l="; 
    request(base_url + keyword + "&l=", function(err, resp, body) { 
     if (err) return callback(err); 

     $ = cheerio.load(body); 
     num_str = $("#searchCount")[0].children[0].data.split(" ").reverse()[0]; 
     num_str = num_str.replace(/\./, ""); 
     num_str = num_str.replace(/,/, ""); 

     stats.push([keyword, num_str]); 

     return callback(); 
    }); 
}, function(err) { 
    if (err) throw err; 
    console.log(stats); 
}); 

Vorausgesetzt, dass Sie die jeweils search_words auf einen Wert zuordnen, sollten Sie async.map() stattdessen betrachten verwenden. Auf diese Weise benötigen Sie das separate Array stats nicht.

.each() und .forEach() wurden als Synonyme verwendet, aber in den letzten Versionen wurde .forEach() entfernt.

+0

Sie haben Recht über den Callback Teil. Aber anstatt einen Callback zurückzugeben 'return callback();' würde ich nicht einfach 'callback();'? Wird dies nicht im Continuation Passing Style (CPS) verwendet: Anstatt von einer Funktion zurückzukehren, geben Sie die Kontrolle an eine andere Funktion weiter. – Ugur

+0

Auch wenn ich eine 'console.log ([Schlüsselwort, num_str]);' vor 'stats.push ([Schlüsselwort, num_str])' Ich bekomme die richtigen Daten. Warum wird 'stats.push ([keyword, num_str]);' nicht an das stats-Array angehängt? Oder ist es? – Ugur

+0

Btw danke für den Zeiger auf async.map()! – Ugur

0

ziemlich sicher, müssen Sie das Ergebnis in der Callback Passback, wenn Sie eine Antwort von Anfrage Rückkehr

request(base_url + keyword + "&l=", function(err, resp, body) { 
     if (err) throw err; 
     $ = cheerio.load(body); 
     num_str = $("#searchCount")[0].children[0].data.split(" ").reverse()[0]; 
     num_str = num_str.replace(/\./, ""); 
     num_str = num_str.replace(/,/, ""); 

     stats.push([keyword, num_str]); 
    }); 
+0

Rückruf (Null, Körper) –

Verwandte Themen