Javascript 所有操作完成后,如何让node.js返回数据
我只是在学习服务器端JavaScript,所以请容忍我犯的任何明显错误 我正在尝试编写一个文件解析器,它对目录中的HTML文件进行操作,并在解析完所有文件后返回一个JSON字符串。我从一个文件开始,它工作得很好。它从运行在同一台机器上的Apache加载资源,注入jquery,进行解析并返回我的JSONJavascript 所有操作完成后,如何让node.js返回数据,javascript,node.js,server-side,readdir,Javascript,Node.js,Server Side,Readdir,我只是在学习服务器端JavaScript,所以请容忍我犯的任何明显错误 我正在尝试编写一个文件解析器,它对目录中的HTML文件进行操作,并在解析完所有文件后返回一个JSON字符串。我从一个文件开始,它工作得很好。它从运行在同一台机器上的Apache加载资源,注入jquery,进行解析并返回我的JSON var request = require('request'), jsdom = require('jsdom'), sys = require('sys'), http
var request = require('request'),
jsdom = require('jsdom'),
sys = require('sys'),
http = require('http');
http.createServer(function (req, res) {
request({uri:'http://localhost/tfrohe/Car3E.html'}, function (error, response, body) {
if (!error && response.statusCode == 200) {
var window = jsdom.jsdom(body).createWindow();
jsdom.jQueryify(window, 'http://ajax.googleapis.com/ajax/libs/jquery/1.4.4/jquery.min.js', function (window, jquery) {
// jQuery is now loaded on the jsdom window created from 'body'
var emps = {};
jquery("tr td img").parent().parent().each(function(){
var step = 0;
jquery(this).children().each(function(index){
if (jquery(this).children('img').attr('src') !== undefined) {
step++;
var name = jquery(this).parent().next().next().children('td:nth-child('+step+')').children().children().text();
var name_parts = name.split(",");
var last = name_parts[0];
var name_parts = name_parts[1].split(/\u00a0/g);
var first = name_parts[2];
emps[last + ",_" + first] = jquery(this).children('img').attr('src');
}
});
});
emps = JSON.stringify(emps);
//console.log(emps);
res.writeHead(200, {'Content-Type': 'text/plain'});
res.end(emps);
});
} else {
res.writeHead(200, {"Content-Type": "text/plain"});
res.end("empty");
//console.log(response.statusCode);
}
});
}).listen(8124);
现在,我尝试将其扩展到使用常规文件系统(fs),获取目录中的所有HTML文件,并以相同的方式解析它们,并在解析完所有文件后返回一个组合的JSON对象。这是我到目前为止所做的,但它不起作用
var sys = require("sys"),
fs = require("fs"),
jsdom = require("jsdom"),
emps = {};
//path = '/home/inet/www/media/employees/';
readDirectory = function(path) {
fs.readdir(path, function(err, files) {
var htmlfiles = [];
files.forEach(function(name) {
if(name.substr(-4) === "html") {
htmlfiles.push(name);
}
});
var count = htmlfiles.length;
htmlfiles.forEach(function(filename) {
fs.readFile(path + filename, "binary", function(err, data) {
if(err) throw err;
window = jsdom.jsdom(data).createWindow();
jsdom.jQueryify(window, 'http://ajax.googleapis.com/ajax/libs/jquery/1.4.4/jquery.min.js', function (window, jquery) {
jquery("tr td img").parent().parent().each(function(){
var step = 0;
jquery(this).children().each(function(index){
if (jquery(this).children('img').attr('src') !== undefined) {
step++;
var empname = jquery(this).parent().next().next().children('td:nth-child('+step+')').children().children().text();
var name_parts = empname.split(",");
var last = name_parts[0];
var name_parts = name_parts[1].split(/\u00a0/g);
var first = name_parts[2]
emps[last + ",_" + first] = jquery(this).children('img').attr('src');
}
});
});
});
});
});
});
}
readDirectory('/home/inet/www/media/employees/', function() {
console.log(emps);
});
在本例中,目录中有2个html文件。如果我在htmlfiles.forEach()
过程中console.log(emps)
,它会以我期望的方式显示第一个文件的结果,然后显示两个文件的结果。如何将EMP返回到readDirectory,以便根据需要输出它
完成的脚本
在回答下面的问题之后,下面是一个完整的脚本,其中包含一个httpServer来提供详细信息
var sys = require('sys'),
fs = require("fs"),
http = require('http'),
jsdom = require('jsdom'),
emps = {};
var timed = setInterval(function() {
emps = {};
readDirectory('/home/inet/www/media/employees/', function(emps) {
});
}, 3600000);
readDirectory = function(path, callback) {
fs.readdir(path, function(err, files) {
var htmlfiles = [];
files.forEach(function(name) {
if(name.substr(-4) === "html") {
htmlfiles.push(name);
}
});
var count = htmlfiles.length;
htmlfiles.forEach(function(filename) {
fs.readFile(path + filename, "binary", function(err, data) {
if(err) throw err;
window = jsdom.jsdom(data).createWindow();
jsdom.jQueryify(window, 'http://ajax.googleapis.com/ajax/libs/jquery/1.4.4/jquery.min.js', function (window, jquery) {
var imagecount = jquery("tr td img").length;
jquery("tr td img").parent().parent().each(function(){
var step = 0;
jquery(this).children().each(function(index){
if (jquery(this).children('img').attr('src') !== undefined) {
step += 1;
var empname = jquery(this).parent().next().next().children('td:nth-child('+step+')').children().children().text();
var name_parts = empname.split(",");
var last = name_parts[0];
var name_parts = name_parts[1].split(/\u00a0/g);
var first = name_parts[2]
emps[last + ",_" + first] = jquery(this).children('img').attr('src');
}
});
});
count -= 1;
if (count <= 0) {
callback(JSON.stringify(emps));
}
});
});
});
});
}
var init = readDirectory('/home/inet/www/media/employees/', function(emps) {
});
http.createServer(function (req, res) {
res.writeHead(200, {'Content-Type': 'text/plain'});
res.end(JSON.stringify(emps));
}).listen(8124);
var sys=require('sys'),
fs=要求(“fs”),
http=require('http'),
jsdom=require('jsdom'),
emps={};
var timed=setInterval(函数(){
emps={};
readDirectory('/home/inet/www/media/employees/',函数(emps){
});
}, 3600000);
readDirectory=函数(路径,回调){
fs.readdir(路径、函数(错误、文件){
var htmlfiles=[];
files.forEach(函数(名称){
if(name.substr(-4)=“html”){
htmlfiles.push(名称);
}
});
var count=htmlfiles.length;
forEach(函数(文件名){
读取文件(路径+文件名,“二进制”,函数(错误,数据){
如果(错误)抛出错误;
window=jsdom.jsdom(data.createWindow();
jQueryify(窗口,'http://ajax.googleapis.com/ajax/libs/jquery/1.4.4/jquery.min.js,函数(窗口,jquery){
var imagecount=jquery(“tr td img”)。长度;
jquery(“tr td img”).parent().parent().each(function()){
var阶跃=0;
jquery(this).children().each(函数(索引){
if(jquery(this).children('img').attr('src')!==未定义){
步骤+=1;
var empname=jquery(this.parent().next().next().children('td:nth child('+step+')).children().children().text();
var name_parts=empname.split(“,”);
var last=name_parts[0];
变量名称零件=名称零件[1]。拆分(/\u00a0/g);
var first=名称\部件[2]
emps[last+”,“+first]=jquery(this).children('img').attr('src');
}
});
});
计数-=1;
如果(count你似乎做错了一点
readDirectory('/home/inet/www/media/employees/', function() {
console.log(emps);
});
但您已将函数定义为:
readDirectory = function(path) {
回调参数在哪里?请尝试以下操作:
readDirectory = function(path, callback) {
然后在emps[last+”,“+first]=jquery(this).children('img').attr('src');
put
callback.call(null, emps);
无论循环执行多少次,您的回调函数都将被调用。如果您希望它一次返回所有回调函数,您需要计算循环将运行多少次,一直计算到该数字,然后在emps数组中充满您需要的数据时调用您的回调函数。这确实是一大堆代码错误
您永远不会调用提供给readDirectory
您需要跟踪已解析的文件,在解析所有文件时,调用回调并提供emp
这应该起作用:
var sys = require("sys"),
fs = require("fs"),
jsdom = require("jsdom"),
//path = '/home/inet/www/media/employees/';
// This is a nicer way
function readDirectory(path, callback) {
fs.readdir(path, function(err, files) {
// make this local
var emps = {};
var htmlfiles = [];
files.forEach(function(name) {
if(name.substr(-4) === "html") {
htmlfiles.push(name);
}
});
// Keep track of the number of files we have parsed
var count = htmlfiles.length;
var done = 0;
htmlfiles.forEach(function(filename) {
fs.readFile(path + filename, "binary", function(err, data) {
if(err) throw err;
window = jsdom.jsdom(data).createWindow();
jsdom.jQueryify(window, 'http://ajax.googleapis.com/ajax/libs/jquery/1.4.4/jquery.min.js', function (window, jquery) {
jquery("tr td img").parent().parent().each(function(){
var step = 0;
jquery(this).children().each(function(index){
if (jquery(this).children('img').attr('src') !== undefined) {
step++;
var empname = jquery(this).parent().next().next().children('td:nth-child('+step+')').children().children().text();
var name_parts = empname.split(",");
var last = name_parts[0];
var name_parts = name_parts[1].split(/\u00a0/g);
var first = name_parts[2]
emps[last + ",_" + first] = jquery(this).children('img').attr('src');
}
});
});
// As soon as all have finished call the callback and supply emps
done++;
if (done === count) {
callback(emps);
}
});
});
});
});
}
readDirectory('/home/inet/www/media/employees/', function(emps) {
console.log(emps);
});
谢谢你,罗宾,如果我理解正确,我需要做两次循环。一次计算目标,然后第二次构建我的对象?如果你使用jqueryify,你应该能够做类似jquery(this.children().lengthI将imagecount设置为jquery(“tr td img”).length。关于变量作用域是否有一些我不了解的地方?我看不到fs.readFile()函数中的计数。我试图执行类似于if的操作(再次计算为他人工作而不是让他们学习:/呃,对不起?他只是遗漏了一些片段,他并没有要求一个完整的解决方案,你们的问题是什么?通过编辑代码和写评论或以更抽象的方式挑出错误来向他人展示什么是错的都是有效的。谢谢Ivo。这可以通过一个小的编辑来实现,但我不明白回调(EMP)为什么要放在它所在的位置。为什么要在jsdom.jqueryify()内部,而不是在fs.readFile()结束之前放在外部?我真的想了解jqueryify是一个异步函数,它的作用域与readFile回调不同