Как я могу получить node.js для возврата данных после завершения всех операций? - PullRequest
3 голосов
/ 14 декабря 2010

Я только изучаю серверный 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-файлы в каталоге и анализируют их одинаково и возвращают один объединенный объект 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(), он показывает мне результаты из первого файла, а затем результаты для обоих файлов вместе, как я ожидаю.Как мне получить 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);

Ответы [ 2 ]

4 голосов
/ 14 декабря 2010

Конечно, это много кода, пара ошибок.

  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);
});
1 голос
/ 14 декабря 2010

Вы, кажется, делаете это немного неправильно

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 заполнен данными тебе нужно.

...