我有一个使用模块cherio从网站获取数据的函数。
现在我想在一个关键字数组上迭代这个函数,在名为stats的数组中收集中间结果,最后通过console.log()
每当我运行此脚本时,它会快速触发异步函数并打印一个空的stats数组。
现在我的问题是:我如何等待异步函数完成,以便在填充/完成时将数组打印到控制台。
我已经google了很多搜索堆栈溢出。似乎有很多方法可以实现我的目标,但节点中最惯用的方法是什么?
以下是解决问题的方法:
var request = require("request"),
cheerio = require("cheerio"),
base_url = "http://de.indeed.com/Jobs?q="; // after equal sign for instance: sinatra&l=
/* 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",
"java", "grails", "groovy",
"php", "symfony", "laravel"
];
var counter = 0;
var stats = [];
function getStats(keyword) {
url = base_url + keyword + "&l=";
request(url, function(err, resp, body) {
if(!err) {
$ = cheerio.load(body);
data = $("#searchCount")[0].children[0].data.split(" ").reverse()[0];
stats.push([keyword, data]);
counter++;
}
// list complete?
if (counter === search_words.length) {
console.log(stats);
}
});
}
for (var j=0; j<= search_words.length; j++) {
getStats(search_words[j]);
}
答案 0 :(得分:3)
Promise是处理异步操作的最佳解决方案。
Promise.all(search_words.map(function(keyword) {
return new Promise(function(resolve, reject) {
request(base_url + keyword + "&l=", function(err, resp, body) {
if (err) {
return reject(err);
}
$ = cheerio.load(body);
resolve([keyword, $("#searchCount")[0].children[0].data.split(" ").reverse()[0]]);
});
});
})).then(function(stats) {
console.log(stats);
});
&#13;
答案 1 :(得分:1)
我能想到的最常见的方法是使用像Q这样的承诺库。
npm install --save q
然后在您的代码中使用它:
var Q = require('q');
var requestFn = q.denodeify(request);
然后迭代你的值:
var promises = search_words.map(function(keyword) {
url = base_url + keyword + "&l=";
return requestFn(url);
});
Q.all(promises).then(function(values) {
//values will contain the returned values from all requests (in array form)
}, function(rejects) {
//rejected promises (with errors, for example) land here
});
来自Q的denodeify函数基本上将基于回调的函数转换为一个返回promise的函数(未来值的一个步骤,只要它在那里)。该函数是requestFn(为它找到一个更好的名字!)。所有这些承诺都收集在一个数组中,传递给Q.all以确保所有承诺都得到满足(如果一个被拒绝,其他承诺也被拒绝)。
如果这不是您的预期行为:有很多方法可以与优秀的Q库一起玩。请参阅文档:https://github.com/kriskowal/q
我没有对此代码进行防弹测试。你可能需要稍微玩一下,但它应该让你知道如何正确地做这样的事情。计数器上升通常是处理异步代码的一种非常不可靠的方式。
答案 2 :(得分:0)
除了用于解决问题的常用(和正确)方法之外,还有一些模块可以让您编写同步的代码,如果您真的想要的话。
尝试google for“nodejs synchronous”将某些链接发送到nodejs模块和/或方法,以便在nodejs中编写同步代码,但我认为它们仅对某些特定问题有用(我自己从未使用过它们)