数组元素未定义时序问题?



所以我一直在玩网络抓取,我的主要工作都是有效的,但是当我尝试输出数组元素时,它们都是未定义的(请参阅底部的输出(。我觉得这可能与时间问题有关,我这么说是因为价格永远不会像请求需要不同的时间来回答一样顺序相同。如果这是问题所在,如何让它们同步?谢谢!

const request = require('request');
const cheerio = require('cheerio');
const fs = require('fs');
const writeStream = fs.createWriteStream('post.csv');
var numbers = ["2202917",
"2205112",
"3514318",
"3514561",
"3585503",
"3585704",
"3610075",
"5132753",
"5247359",
"5247360"];
var y =0;
var partNumber1 ="";
var price1 ="";
writeStream.write('PartNumber,Price n');
for (y=0; y < numbers.length; y++){
request(url + numbers[y], function(error, response, html) {
if (!error && response.statusCode == 200) {
const $ = cheerio.load(html);
price1 =$('.price').text().replace(/ss+/g,'');
partNumber1 =numbers[y];
console.log(partNumber1,' ',price1);
writeStream.write(`${partNumber1}, ${price1} n`);
}
});
}

输出

C:Program Filesnodejs>node mp2.js
undefined ' ' '$8.99'
undefined ' ' '$127.88'
undefined ' ' '$43.22'
undefined ' ' '$27.38'
undefined ' ' '$21.41'
undefined ' ' '$41.46'
undefined ' ' '$21.57'
undefined ' ' '$47.99'
undefined ' ' '$1267.30'
undefined ' ' '$22.04'
C:Program Filesnodejs>

你正在做 request(( 调用,这是一个异步调用。所以,它不会有序。 这是一个更简单的例子,我将用它来解释替代方案。

使用超时到不同的时间间隔来模拟请求调用。

var numbers = ["2202917",
"2205112",
"3514318",
"3514561",
"3585503",
"3585704",
"3610075",
"5132753",
"5247359",
"5247360"];
/*
for (var y=0; y < numbers.length; y++) {
setTimeout(function(error, response, html) {
// the problem here is that it is referring a closure variable. The value of y keeps changing outside, and is not the same as the one you called it with.
// In this particular case, the value of y = numbers.length, and hence the undefined output
console.log(numbers[y]);
}, y % 100);
}
*/
// Alternative 1
// A better way would be like this
for (var y=0; y < numbers.length; y++) {
// doRequest(numbers[y]);
}
function doRequest(partNumber) {
setTimeout(function(error, response, html) {
console.log(partNumber);    
}, partNumber % 100); 
}
// end: Alternative 1
// Alternative 2
// in case you want it to be in sync
async function doSomething() {
for (var y = 0; y < numbers.length; y++) {
await doPromiseRequest(numbers[y]);
}
}
function doPromiseRequest(partNumber) {
return new Promise((resolve, reject) => {
setTimeout(function(error, response, html) {
console.log(partNumber);
resolve();
}, partNumber % 100); 
});
}
doSomething();
// end Alternative 2
/*
another alternative is not calling a separate function, but executing an anonymous function in the loop itself. It is not clean at all and not recommended.
for (var y = 0; y < numbers.length; y++) {
(function (y) {
setTimeout(function(error, response, html) {
// the problem here is that it is referring a closure variable. The value of y keeps changing outside, and is not the same as the one you called it with
console.log(numbers[y]);
}, y % 100);
})(y);
}
*/

最新更新