3

私はサーバーサイドの JavaScript を学んでいるので、私が犯した明らかな間違いについてはご容赦ください。

ディレクトリ内の HTML ファイルを操作し、すべてのファイルが解析されると JSON 文字列を返すファイル パーサーを作成しようとしています。単一のファイルで開始しましたが、正常に動作します。同じマシンで実行されている Apache からリソースをロードし、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 ファイルを取得して同じ方法で解析し、すべてのファイルが解析されたら、1 つの結合された 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 ファイルがあります。console.log(emps)途中でhtmlfiles.forEach()最初のファイルの結果が表示された場合、両方のファイルの結果が期待どおりに表示されます。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);
4

2 に答える 2

4

それは確かに多くのコードといくつかの間違いです。

  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);
});
于 2010-12-14T17:24:52.760 に答える
1

あなたはこれを少し間違っているようです

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');プット

callback.call(null, emps);

コールバック関数は、ループが何回も呼び出されます。それらすべてを一度に返したい場合は、ループが実行される回数をカウントし、その回数までカウントアップしてから、emps 配列がデータでいっぱいになったときにコールバックを呼び出す必要があります。あなたが必要です。

于 2010-12-14T17:23:38.293 に答える