node.js等待文件操作完成

node.js等待文件操作完成,node.js,web-services,asynchronous,Node.js,Web Services,Asynchronous,我是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 = ""

我是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)
注意:我不确定你想用
res.write(out)
message.pipe(res)
做什么。这将把ruby脚本的输出写入响应,然后看起来您正在将请求主体管道化。实际上,
message.pipe(res)
行不起作用,因为您将尝试从可写流进行管道传输,而这是无法做到的对于这个答案,我假设您不想要
消息.pipe(res)
行;如果我错了,请纠正我。

简单/快速回答 最简单的答案是侦听
req
上的
end
事件,然后在该事件触发时执行程序,等等:

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.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_文件名,{flags:'a'})

谢谢Mike S。message.pipe(res)和res.write(out)是多余的…但是我做了一些研究并使用了async.瀑布包,下面的内容对我有用。但我会接受你的优化建议

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

我想你的整个问题归结为:如何通知我完成
req.pipe
?是吗?正确,我需要提取发送的所有数据,并将其写入代码部分的文件中。