Javascript 如何对node.js非阻塞代码中的代码执行进行排序?
我已经用Javascript 如何对node.js非阻塞代码中的代码执行进行排序?,javascript,node.js,callback,request,nonblocking,Javascript,Node.js,Callback,Request,Nonblocking,我已经用node.js构建了一个网络爬虫程序,但是node.js的一个主要特性是非阻塞代码,这很好,但在我的例子中它破坏了我的程序。以下是我的程序过去的工作方式: 首先,它为该网站发出请求,并找到指向的所有链接 在页面上通过的所有公司 然后我有了for循环,它修改了这个数组 然后我有一个请求,它位于for循环中,抛出 公司URL数组,用于查找每个公司中的所有产品URL 页面 然后我有一个for循环,用于修改产品URL数组 然后我有另一个在for循环中的请求 抛出产品数组并获取每个产品的价格和 将
node.js
构建了一个网络爬虫程序,但是node.js
的一个主要特性是非阻塞
代码,这很好,但在我的例子中它破坏了我的程序。以下是我的程序过去的工作方式:
请求
,并找到指向的所有链接
在页面上通过的所有公司李>
for
循环,它修改了这个数组李>
请求
,它位于for循环中,抛出
公司URL数组,用于查找每个公司中的所有产品URL
页面李>
for
循环,用于修改产品URL数组李>
for
循环中的请求
抛出产品数组并获取每个产品的价格和
将其存储到字典(对象)中,其中键是
产品和价值就是价格李>
回调
,但结果并不理想。因为这里有一个回调的简单示例:
function some_function(arg1, arg2, callback) {
var my_number = (arg1 - arg2) * arg2;
callback(my_number);
}
some_function(20, 15, function(num) {
console.log("callback called! " + num);
});
但我无法想象如何进行包含6个函数的回调。也许有一种方法,但不是用我对回调的了解。这是我的程序的一个演示版本,没有回调
:
var request = require('request');
var cheerio = require('cheerio');
var companiesUrls = [];
var url = '';
var companiesUrls2 = [];
var carsUrls = [];
var carsOwnerReview = {};
var carReviewUrl = [];
var site = '...'
var companiesPath = '/companies'
///step 1\\\
request(site+companiesPath, function(err, resp, body){
if(!err && resp.statusCode == 200){
var $ = cheerio.load(body);
$('a', '#group-content').each(function(){
var url = $(this).attr('href');
companiesUrls.push(url);
});
};
});
///step 2\\\
for(var i=0;i<companiesUrls.length;i+=2){
companiesUrls2.push(companiesUrls[i]);
};
///step 3\\\
for(var i=0;i<companiesUrls2.length;i++){
request(site+companiesUrls2[i], function(err, resp, body){
if(!err && resp.statusCode == 200){
var $ = cheerio.load(body);
$('h3.edition-title').children().children().each(function(){
var url = $(this).attr('href');
carsUrls.push(url);
});
};
});
};
///step 4\\\
for(var i=0;i<carsUrls.length;i++){
carReviewUrl.push(carsUrls[carsUrls.length-1].slice(0,-7)+'/owner-reviews');
};
///step 5\\\
for(var i=0;i<carReviewUrl.length;i++){
request(site+carReviewUrl[i], function(err, resp, body){
if(!err && resp.statusCode == 200){
var $ = cheerio.load(body);
var model = $('#page-title').text();
$('span.total-votes').children().each(function(){
var reviewNum = $(this).text();
carsOwnerReview[model] = reviewNum;
});
};
});
}
///step 6\\\
var keysSorted = Object.keys(carsOwnerReview).sort(function(a,b){return carsOwnerReview[a]-carsOwnerReview[b]});
var keysSortedReversed = keysSorted.reverse();
var request=require('request');
var cheerio=需要('cheerio');
var companiesUrls=[];
var url='';
var CompanyUrls2=[];
var carsUrls=[];
var carsOwnerReview={};
var carReviewUrl=[];
var site='…'
var companiesPath='/companies'
///第一步\\\
请求(站点+公司路径、功能(错误、响应、正文){
如果(!err&&resp.statusCode==200){
var$=总负荷(车身);
$('a','#组内容')。每个(函数(){
var url=$(this.attr('href');
companiesURL.push(url);
});
};
});
///步骤2\\\
对于(var i=0;i如果你想用JavaScript/node.js认真编程,你必须深刻理解js是异步的,除了你的代码之外,一切都是并行的
这意味着在您的情况下,除非您的所有代码都已终止,否则不会调用回调。因此,在for循环中调用异步函数应始终使所有警告灯变为红色
以下是正确设计的代码:
var request = require('request');
var cheerio = require('cheerio');
var companiesUrls = [];
var url = '';
var companiesUrls2 = [];
var carsUrls = [];
var carsOwnerReview = {};
var carReviewUrl = [];
var site = '...'
var companiesPath = '/companies'
///step 1\\\
request(site+companiesPath, function(err, resp, body){
if(!err && resp.statusCode == 200){
var $ = cheerio.load(body);
$('a', '#group-content').each(function(){
var url = $(this).attr('href');
companiesUrls.push(url);
});
};
///step 2\\\
for(var i=0;i<companiesUrls.length;i+=2){
companiesUrls2.push(companiesUrls[i]);
};
///step 3\\\
function processCompaniesUrls2( i, callback_pcu2 ) {
if( i<companiesUrls2.length ) {
request(site+companiesUrls2[i], function(err, resp, body){
if(!err && resp.statusCode == 200){
var $ = cheerio.load(body);
$('h3.edition-title').children().children().each(function(){
var url = $(this).attr('href');
carsUrls.push(url);
});
};
processCompaniesUrls2( i+1, callback_pcu2 );
});
} else {
callback_pcu2();
}
}
processCompaniesUrls2( 0, function() {
///step 4\\\
for(var i=0;i<carsUrls.length;i++){
carReviewUrl.push(carsUrls[carsUrls.length-1].slice(0,-7)+'/owner-reviews');
};
///step 5\\\
function processCarReviewUrl( i, callback_pcru ) {
if( i<carReviewUrl.length ) {
request(site+carReviewUrl[i], function(err, resp, body){
if(!err && resp.statusCode == 200){
var $ = cheerio.load(body);
var model = $('#page-title').text();
$('span.total-votes').children().each(function(){
var reviewNum = $(this).text();
carsOwnerReview[model] = reviewNum;
});
};
processCarReviewUrl( i+1, callback_pcru );
});
} else {
callback_pcru();
}
}
processCarReviewUrl( 0, function() {
///step 6\\\
var keysSorted = Object.keys(carsOwnerReview).sort(function(a,b){return carsOwnerReview[a]-carsOwnerReview[b]});
var keysSortedReversed = keysSorted.reverse();
});
});
});
var request=require('request');
var cheerio=需要('cheerio');
var companiesUrls=[];
var url='';
var CompanyUrls2=[];
var carsUrls=[];
var carsOwnerReview={};
var carReviewUrl=[];
var site='…'
var companiesPath='/companies'
///第一步\\\
请求(站点+公司路径、功能(错误、响应、正文){
如果(!err&&resp.statusCode==200){
var$=总负荷(车身);
$('a','#组内容')。每个(函数(){
var url=$(this.attr('href');
companiesURL.push(url);
});
};
///步骤2\\\
对于(var i=0;iI使用promissions()来实现这一点……对于我来说,这使事情更容易理解和管理