我是node.js的新手,我需要编写一个获取数据并将其写入文件的Web服务器。然后该文件用于外部程序。
我的问题是node.js在数据完全写入文件之前执行外部程序。如何在执行外部程序之前等待它完成
var http = require('http')
var map = require('through2-map')
var fs = require('fs')
var str = ""
var sh = require('execSync');
var tmp_filename = ""
function random (low, high) {
return Math.random() * (high - low) + low;
}
function execute_program(){
var command = 'ruby ' + __dirname + '/check_content.rb --file '+ tmp_filename
var result = sh.exec(command);
console.log('return code ' + result.code);
console.log('stdout + stderr ' + result.stdout);
return result.stdout
}
function write_to_file (chunk){
str = chunk.toString();
fs.appendFile(tmp_filename, str, function (err){
if (err) throw err;
console.log('The "data to append" was appended to file!');
}
)
}
var server = http.createServer( function(req, res){
tmp_filename = '/tmp/tmp_template_' + random(1000, 99999) + '.template'
res.writeHead(200, {'Content-Type': 'text/plain'});
message = req.pipe(map(function (chunk, res) {
write_to_file(chunk);
}))
var out = execute_program();
res.write(out)
message.pipe(res)
}
)
server.listen(8000)
答案 0 :(得分:0)
注意:我不确定您使用res.write(out)
然后message.pipe(res)
尝试了什么。这会将ruby脚本的输出写入响应,然后看起来你在此之后管理请求体。实际上,message.pipe(res)
行无法正常工作,因为您将尝试从可写流中进行管道传输,而您无法做到这一点。 为了这个答案的目的,我假设你不想要message.pipe(res)
行;如果我错了,请纠正我。
最简单的答案是在end
上监听req
事件,然后在事件触发时执行您的程序等:
var server = http.createServer( function(req, res){
tmp_filename = '/tmp/tmp_template_' + random(1000, 99999) + '.template'
res.writeHead(200, {'Content-Type': 'text/plain'});
req.on('end', function() {
var out = execute_program();
res.write(out);
res.end();
});
req.pipe(map(function (chunk, res) {
write_to_file(chunk);
}));
}
)
fs.createWriteStream()
您也可以使用fs.createWriteStream()
而不是使用fs.appendFile()
附加数据块。那看起来像是:
var server = http.createServer( function(req, res){
tmp_filename = '/tmp/tmp_template_' + random(1000, 99999) + '.template'
res.writeHead(200, {'Content-Type': 'text/plain'});
req.on('end', function() {
var out = execute_program();
res.write(out);
res.end();
});
req.pipe(fs.createWriteStream(tmp_filename));
}
)
有了这些功能,您就可以删除整个write_to_file
功能。
如果您碰巧为临时文件获取相同的随机数,那么这也可以防止您遇到的问题;使用当前代码,您将附加到现有文件,这可能不是您想要的。如果由于某种原因你做想要在这种情况下附加到文件,你可以将a
标记(用于追加)传递给fs.createWriteStream
:fs.createWriteStream(tmp_filename, {flags: 'a'});
答案 1 :(得分:0)
感谢Mike S. message.pipe(res)和res.write(out)是多余的...但我做了一些研究并使用了async.waterfall包,以下内容对我有用。但会采取你的建议进行优化
var http = require('http');
var map = require('through2-map');
var fs = require('fs');
var str = "";
var sh = require('execSync');
var async = require('async');
var tmp_filename = "";
function random (low, high) {
return Math.random() * (high - low) + low;
}
function write_to_file (chunk){
str = chunk.toString();
fs.appendFile(tmp_filename, str, function (err){
if (err) throw err;
console.log('The "data to append" was appended to file!');
}
)
}
function execute_program(){
var command = 'ruby ' + __dirname + '/check_content --file ' + tmp_filename
var result = sh.exec(command);
console.log('return code ' + result.code);
console.log('stdout + stderr ' + result.stdout);
return result.stdout
}
async.waterfall([
function(callback){
var server = http.createServer(function(req, res){
callback(null, req, res)
}
).listen(8000);
},
function(req, res, callback){
tmp_filename = '/tmp/tmp_template_' + random(1000, 99999) + '.template'
var message = req.pipe(map(function (chunk) {
write_to_file(chunk);
}))
setTimeout(function () {
callback(null, req, res, message);
}, 666);
},
function(req, res, message, callback){
var out = execute_program()
res.write(out)
message.pipe(res)
callback(null, 'done');
}
])