javascript - 一旦所有操作完成,如何让 node.js 返回数据

标签 javascript node.js server-side readdir

我只是在学习服务器端 JavaScript,所以请原谅我犯的任何明显错误。

我正在尝试编写一个文件解析器,它对目录中的 HTML 文件进行操作,并在解析完所有文件后返回一个 JSON 字符串。我用一个文件启动它,它工作正常。它从运行在同一台机器上的 Apache 加载资源,注入(inject) jquery,进行解析并返回我的 JSON。

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) 它会显示第一个文件的结果,然后按照我期望的方式显示两个文件的结果。如何让 emps 返回到 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);

最佳答案

这肯定是很多代码和一些错误。

  1. 您永远不会调用您提供给 readDirectory 的回调函数
  2. 您需要跟踪已解析的文件,当您解析所有文件时,调用回调并提供 emps

这应该有效:

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);
});

关于javascript - 一旦所有操作完成,如何让 node.js 返回数据,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/4442046/

相关文章:

javascript - 当需要模块时,花括号的作用是什么?

node.js - 基于 Promise 的 Node http 框架?

Linux 上的 C# 服务器可伸缩性问题

node.js - 如何解决这个问题? npm WARN config global `--global` 、 `--local` 已弃用。使用 `--location=global` 代替

node.js - 在路由文件之外使用 res.send()

javascript - 在服务器上处理 Javascript

jquery - 服务器端模板、客户端模板 - 自动转换?

javascript - 如何在选项选择上使用 jquery 自动完成引起回发?

javascript - jqtree无法使用loadDataFromUrl函数加载数据

javascript - 不规则按钮形状背景图片 纯 CSS 或 Javascript ie6 兼容。 (我知道..古老的)我不能使用 jquery