在节点.js中强制使用顺序代码
Forcing Sequential Code in node.js
我终于弄清楚了回调在node.js中是如何工作的,但是我现在正在尝试让我的代码按顺序执行。
目标是(按顺序):
- 将网址加载到欢呼中
- 分析页面上
<tbody>
中的每个<td>
。 - 将文本元素加载到数据数组后,回调。
- 在完整数据数组上调用循环透数据。
- 遍历数据数组并调用每个数组上的 lookForPlayer 数组一,其中:
- 在我的数据库中运行一个与从文本元素,如果我的数据库中没有匹配项,请插入它们(我有它现在只是打印到控制台以进行测试)。
最终目标是遍历每个页面(每个日期都有一个单独的 URL,所以我正在循环浏览日期)并插入一次不在我的数据库中的玩家。问题是它在执行 INSERT 查询之前会经历每个 SELECT,因此它会多次插入它们。
这是我正在解析的页面,如果有帮助的话:http://www.basketball-reference.com/friv/dailyleaders.cgi?month=12&day=29&year=2014
这是我的代码:
function loadPage (url, callback){
request(url, function(err, response, body){
if(!err && response.statusCode ==200){
var $ = cheerio.load(body);
rowsRemaining = $.length;
$('td', 'tbody').each(function(){
var text = $(this).text();
data.push(text);
rowsRemaining -= 1;
console.log('rows left: ',rowsRemaining);
});
}
if (rowsRemaining == 0){
console.log('$ length: ',$.length);
callback(data);
}
});
}
function loopThroughData (data, callback){
for(i=1;i<data.length;i+=26){
lookForPlayer(data[i].replace("'",""),function(name){
/* var insertPlayer = connection.query(
'INSERT INTO player (provider_id, team_id, position_id, name) VALUES (1, (SELECT id FROM team WHERE slug = "'+data[i+1]+'"),1,"'+name+'");',function(err,result,fields){
}); */
console.log('i is currently = ',i);
});
}
callback();
}
function lookForPlayer(name, callback){
console.log('Looking for Player...');
var selectPlayer = connection.query(
"SELECT * FROM player WHERE name = '"+name+"'", function(err, rows, fields){
if(err) throw err;
if(rows.length==0){
callback(name);
}
});
}
//loop through every day since the season started
for (d = seasonStart; d <= Date.now(); d.setDate(d.getDate() + 1)){
console.log('d = ',d);
loadPage(baseURL+(d.getMonth()+1)+'&day='+d.getDate()+'&year='+d.getFullYear(),function(data){
console.log('Page loaded...');
loopThroughData(data,function(){
});
});
}
如您所见,我尝试添加一个 rowsRemaining 变量,该变量旨在确保在调用 loadPage 函数中的回调之前我已经解析了整个文件,但它从未达到这一点。请注意,我在这些函数(行剩余、数据等)之前初始化了很多这些变量。
它似乎也在完全加载、解析和插入第一页之前遍历每个日期,这是它不应该做的。
这是基于@Brant答案的更新代码
function loadPage (url, callback){
request(url, function(err, response, body){
if(!err && response.statusCode ==200){
var $ = cheerio.load(body);
console.log(url);
$('td', 'tbody').each(function(){
var text = $(this).text();
data.push(text);
});
}
callback(data);
});
}
function loopThroughData (data, callback){
for(i=1;i<data.length;i+=26){
lookForPlayer(data[i].replace("'",""),function(name){
var insertPlayer = connection.query(
'INSERT INTO player (provider_id, team_id, position_id, name) VALUES (1, (SELECT id FROM team WHERE slug = "'+data[i+1]+'"),1,"'+name+'");',function(err,result,fields){
});
});
}
callback(data);
}
function lookForPlayer(name, callback){
var selectPlayer = connection.query(
"SELECT * FROM player WHERE name = '"+name+"'", function(err, rows, fields){
if(err) throw err;
if(rows.length==0){
console.log(name,' was not found in DB!');
callback(name);
}
});
}
//loop through every day since the season started
for (d = seasonStart; d <= Date.now(); d.setDate(d.getDate() + 1)){
validDatesArr.push(d);
}
async.eachSeries(validDatesArr,
function(validDatesArr, callback){
loadPage(baseURL+'/month='+validDatesArr.getMonth()+1+'&day='+validDatesArr.getDate()+'&year='+validDatesArr.getFullYear(),function(data){
loopThroughData(data, function(){
callback();
});
});
}, function(err){
if(!err){
console.log('We processed each date requests one by one');
}
}
);
所以现在它正在逐个加载页面,但它没有在该数据的loopThroughData函数中执行INSERT函数。我想我只会在异步列表中添加另一个函数,但这个特定的函数是调用一个函数,而不是使用匿名函数。
将 for 循环修改为如下所示:
//loop through every day since the season started
var validDatesArr = [];
for (var d = seasonStart; d <= Date.now(); d.setDate(d.getDate() + 1)){
validDatesArr.push(d);
}
async.eachSeries(validDatesArr,
function(d, callback) {
loadPage(baseURL+(d.getMonth()+1)+'&day='+d.getDate()+'&year='+d.getFullYear(),function(data){
console.log('Page loaded...');
loopThroughData(data,function(){
callback();
});
});
}, function(err) {
if(!err) {
console.log('We processed each date request one by one')
}
}
);
并且需要异步,可以在这里找到:https://github.com/caolan/async
npm install async
你可以嵌套异步函数来控制执行流程,就像在序列编程中一样,在厄运金字塔中要小心,另一种解决方案是使用你使用的异步函数的同步版本(如果存在)。如果你不需要它们,你不会被迫编写异步函数,Node.js使用大量的异步函数,因为它是一种非bloking语言,对Web开发非常强大。所以不要在你的函数中使用 asyn 风格和回调!
- javascript函数和代码隐藏函数的执行顺序
- 代码混淆的执行顺序
- 要按顺序执行的异步代码
- 奇怪的javascript代码执行顺序
- 无法让 jQuery 以正确的顺序执行代码
- 为什么Javascript不按顺序执行代码
- Javascript代码的执行顺序
- 调用加载的顺序函数会意外中断代码
- 按顺序运行Js代码
- 按顺序调用javascript代码的替代方法,其间有延迟
- 除了JS,其他语言是否按加载顺序执行代码
- 在节点.js中强制使用顺序代码
- 从 JavaScript 代码中按顺序加载 JavaScript
- Javascript代码执行顺序
- JavaScript 读取代码的顺序
- Node.js代码执行顺序
- html中python代码和javascript代码的执行顺序是什么
- 为什么这个Javascript代码不按顺序执行
- 按顺序执行jquery代码
- Js 代码和 Jquery 在 Dom 中的 ajax 请求的加载顺序