节点生成过程

Node spawn process

无法在以下脚本中找出问题,我想用脚本实现的是拥有一个节点日志服务器,该服务器将侦听 post 以日志标题和日志详细信息作为查询参数的请求,写入文件,然后在 get 请求时作为 json 返回。

问题: 它有时会不断显示加载程序,有时会提供所需的日志。

注: 进程生成是为了在日志记录期间更新浏览器,如果有人有更好的解决方案,请建议

Post 调用:

http://127.0.0.1:8081/log?title="test"&detail="test detail"

代码:

var express = require("express");
var spawn = require('child_process').spawn;
var fs = require("fs");

var srv = express();

var outputFilename = '/tmp/my.json';

function getParamsObject(context) {
    var params = {};

    for (var propt_params in context.params) {
        params[propt_params] = context.params[propt_params];
        //define(params, propt_params, context.params[propt_params]);
    }

    for (var propt_body in context.body) {
        params[propt_body] = context.body[propt_body];
        //define(params, propt_body, context.body[propt_body]);
    }

    for (var propt_query in context.query) {
        params[propt_query] = context.query[propt_query];
        //define(params, propt_query, context.query[propt_query]);
    }

    return params;
}


srv.get("/", function(req, res) {
    res.send("Hello World From Index\n");

});

srv.get("/Main", function(req, res) {
    res.send("Hello World From Main\n");
});

srv.get("/ReadFile", function(req, res) {
    fs.readFile("example_one.txt", function(err, data) {

        if(err) throw err;

        res.send(data.toString());

    });
});

srv.get("/ReadFileJSON", function(req, res) {
    fs.readFile("example_one.txt", function(err, data) {

        if(err) throw err;

        res.setHeader("content-type", "application/json");
        res.send(new Parser().parse(data.toString()));

    });

});


srv.post("/log", function(req, res) {

    var input = getParamsObject(req);

    if(input.detail) {
    var myData = {
        Date: (new Date()).toString(),
                Title: input.title,
                Detail: input.detail
    }

    fs.writeFile(outputFilename, JSON.stringify(myData, null, 4), function(err) {
            if(err) {
                console.log(err);
            }
    }); 
    }
    res.setHeader("content-type", "application/json");
    res.send({message:"Saved"});

});

srv.get("/log", function(req, res) {

    var child = spawn('tail', ['-f', outputFilename]); 
    child.stdout.pipe(res);

    res.on('end', function() {
        child.kill(); 
    });
});


srv.listen(8081);
console.log('Server running on port 8081.');

有几件事似乎是不必要的并发症,可能是您问题的根源。

首先,spawn 似乎是不必要的。看起来您想打开一个文件进行阅读,并在文件中添加内容时随时更新。您可以在 Node 中使用 fs.watch(), fs.watchFile(), or the node-tail 模块执行此操作。这可能比使用 spawn() 创建子进程更可靠。

其次(我认为不太可能是问题的根源),您似乎在 POST 请求中使用了查询字符串参数。虽然并非无效,但这是不寻常的。通常,如果您使用 POST 方法,您将通过 post 发送数据作为请求正文的一部分。如果使用 GET 方法,数据将作为查询字符串发送。如果您不使用正文发送数据,请切换到 GET

澄清问题...

  • 您希望将一些请求写入日志文件。
  • 您想通过 HTTP 有效地执行日志尾部,并且目前正在通过在子进程中生成 tail 来实现。
  • 这不是那么有效。

Problem: It constantly shows loader sometime and gives the required log sometime.

Web 浏览器缓冲数据。当然,您正在发送数据,但是在达到最小缓冲区大小之前,浏览器不会显示它。然后,对于尚未加载所有标记(或本例中的文本)时将显示的内容有一些规则。基本上,您不能将响应流式传输到客户端并可靠地期望客户端对其执行任何操作,直到它完成流式传输。由于您正在拖尾日志,这会使您陷入困境。

您必须做的是找到一种不同的方式将数据发送到客户端。这是网络套接字的一个很好的候选者。您可以在客户端和服务器之间创建持久连接,然后立即处理数据,而不必担心客户端缓冲区。由于您已经在使用 Node.js,我建议研究 Socket.IO,因为它提供了一种快速启动和 运行 网络套接字的方法,以及长轮询 JSON(以及其他) 作为后备,以防当前浏览器上的网络套接字不可用。

接下来,无需像 tail 那样生成另一个进程来读取文件。正如 Trott 指出的那样,有一个 NPM 包可以完全满足您的需求:https://github.com/lucagrulla/node-tail 只需为 line 事件设置一个事件处理程序,然后在网络套接字,以便您的 JavaScript 客户端接收它并立即将其显示给用户。