Node.js + Cheerio:循环内请求
Node.js + Cheerio : Request inside a loop
我正在使用 cheerio、request 和 Node.js。
当我 运行 下面的脚本时,它以错误的顺序输出名称。我相信这是由它的异步性质引起的,我怎样才能让它在 "right" 顺序中工作?我是否需要使用同步包,或者有什么方法可以更改它以使其以同步方式工作?
app.get('/returned', function (req, res) {
for (var y = 0; y < 10; y++) {
var url = "http://example.com" + y + "/person.html";
request(url, function (err, resp, body) {
$ = cheerio.load(body);
var links = $('#container');
var name = links.find('span[itemprop="name"]').html(); // name
if (name == null) {
console.log("returned null");
} else {
console.log(name);
}
});
}
});
不,您不必使用同步包。 IMO 最干净的方法是使用成熟的第 3 方库。
我推荐异步。
async.series
方法将按照给定的顺序执行所有请求函数,然后允许您注册回调以在发出所有请求或发生错误时触发。
Promise 使这变得相对容易:
app.get('/returned', function (req, res) {
let urls = [];
for (let y = 0; y < 10; y++) {
urls.push('http://example.com' + y + '/person.html');
}
Promise.all(urls.map(function (url) {
return new Promise(resolve, reject) {
request(url, function (err, resp, body) {
if (err) {return reject(err);}
let $ = cheerio.load(body);
let links = $('#container');
let name = links.find('span[itemprop="name"]').html(); // name
resolve({name: name, links: links, url: url});
});
});
}).then(function (result) {
result.forEach(function (obj) {
if (obj.name == null) {
console.log(obj.url, "returned null");
} else {
console.log(obj.url, obj.name);
}
});
}).catch(function (err) {
console.log(err);
});
});
我首先创建一个 url 数组来获取,然后我将其映射到一个 promises 数组。当每个请求都完成时,我用名称 url 和链接解析了承诺。当所有的 promise 完成后,我循环遍历将按原始顺序排列的结果。这并行运行。
我正在使用 cheerio、request 和 Node.js。
当我 运行 下面的脚本时,它以错误的顺序输出名称。我相信这是由它的异步性质引起的,我怎样才能让它在 "right" 顺序中工作?我是否需要使用同步包,或者有什么方法可以更改它以使其以同步方式工作?
app.get('/returned', function (req, res) {
for (var y = 0; y < 10; y++) {
var url = "http://example.com" + y + "/person.html";
request(url, function (err, resp, body) {
$ = cheerio.load(body);
var links = $('#container');
var name = links.find('span[itemprop="name"]').html(); // name
if (name == null) {
console.log("returned null");
} else {
console.log(name);
}
});
}
});
不,您不必使用同步包。 IMO 最干净的方法是使用成熟的第 3 方库。
我推荐异步。
async.series
方法将按照给定的顺序执行所有请求函数,然后允许您注册回调以在发出所有请求或发生错误时触发。
Promise 使这变得相对容易:
app.get('/returned', function (req, res) {
let urls = [];
for (let y = 0; y < 10; y++) {
urls.push('http://example.com' + y + '/person.html');
}
Promise.all(urls.map(function (url) {
return new Promise(resolve, reject) {
request(url, function (err, resp, body) {
if (err) {return reject(err);}
let $ = cheerio.load(body);
let links = $('#container');
let name = links.find('span[itemprop="name"]').html(); // name
resolve({name: name, links: links, url: url});
});
});
}).then(function (result) {
result.forEach(function (obj) {
if (obj.name == null) {
console.log(obj.url, "returned null");
} else {
console.log(obj.url, obj.name);
}
});
}).catch(function (err) {
console.log(err);
});
});
我首先创建一个 url 数组来获取,然后我将其映射到一个 promises 数组。当每个请求都完成时,我用名称 url 和链接解析了承诺。当所有的 promise 完成后,我循环遍历将按原始顺序排列的结果。这并行运行。