2016-05-17 23 views
0

一部のURLを非同期で呼び出して結果を収集しようとしています。私は "約束"でそれをやった。今、私はasync.jsの周りを頭で囲んでいます。ここでasync.eachはコールバックを実行しません

は切り取らコードです:

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); 
}); 

thisによると、私は配列を処理した後、それがトリガされますasync.eachする最後の引数としてコールバック関数を渡すことができます。

私の場合、コールバックは決して誘発されないようです。

Btw:Trevor Burnhamは彼の本 "Async Javascript"でasyn.forEach関数を説明しています。これはasync.jsから削除されたようですか?


@robertklepは、iteratee関数にコールバックを追加するヒントを与えました。 //これは、作業バージョンは次のとおりです。アイテムコールバック:

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); 
    } 
}); 

答えて

0

あなたはiterateeがの引数を取得する部分を逃しました。このコールバックは、iterateeが完了したとき(またはエラーが発生したとき)に呼び出される必要があります:

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); 
}); 

あなたが値にsearch_wordsのそれぞれをマッピングしている、あなたが代わりにasync.map()を使用することを検討すべきであることを考えます。そうすれば、別のstats配列は必要ありません。

.each().forEach()は同義語に使用されていましたが、最近のバージョンでは.forEach()が削除されました。

+0

あなたは、コールバックの一部について権利ですからレスポンスを返した後、コールバックで結果をパスバックする必要があります。 しかし、コールバック 'return callback();'を返す代わりに 'callback();'を実行するだけで済むわけではありません。これはContinuation Passing Style(CPS)では使用されていません。あなたが制御する関数から別の関数に戻るのではありません。 – Ugur

+0

また、 'stats.push([keyword、num_str])'の前に 'console.log([keyword、num_str]);'を実行すると正しいデータが得られます。 'stats.push([keyword、num_str]);はなぜstats配列に追加されないのですか?またはそれは? – Ugur

+0

Btwはasync.map()へのポインタをありがとう! – Ugur

0

はかなり確信してあなたが要求

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

コールバック(null、body) –

関連する問題