【问题标题】:How to timeout an fs.read in node.js?如何使 node.js 中的 fs.read 超时?
【发布时间】:2014-01-15 11:37:30
【问题描述】:

我尝试使用 fs.read 从文件描述符中读取。回调函数被调用 拿到数据后。它工作正常。

但现在我想实现一个超时机制:如果 fs.read 在超时内没有获取数据,它应该停止读取。

如何让 fs.read 停止阅读?它仍然挂在后台试图阅读。

我大致做了以下事情:

...
var fd = fs.openSync("/dev/ttyUSB0", 'rs+');
...
...
var bout = new Buffer(string,'binary');
fs.write(fd, bout, 0, bout.length,undefined,function(err, written, buffer) {
  console.log("error writing: "+err);

  var bin = new Buffer(1);
  fs.read(fd,bin,0,1,undefined,function(err,read,buffer) {
    console.log("got it: "+bin);
  });
});
...
...

我想写一些东西到 /dev/ttyUSB0 并阅读答案,但有时没有答案。如果发生这种情况,读取应该超时,以便我可以开始另一个写入/读取。

谢谢

我尝试使用 Timeout 并关闭它,但它不起作用,这是一个示例: 您必须为测试制作“mkfifo 文件”。

var fs=require('fs');

console.log("open file");

fs.open('file', 'r+', function(err,fd) {

  console.log("start reading on "+fd);

  var length=5;

  var data = new Buffer(length);
  data.fill("-");

  setTimeout(function(){
    console.log("timeout");
    console.log("close fd "+fd);
    fs.close(fd,function(err) {
      console.log("close done: "+err);
    });
  }, 5000);

  fs.read(fd, data, 0, length,undefined, function(error, got) {
    console.log("error: "+error);
    console.log("got callback: "+data);
  });

  console.log("done");
});

fs.close 不起作用。关闭后,您可以创建一个“echo test > file”,然后读取获取数据。读取已关闭的文件句柄?

有什么想法吗?

【问题讨论】:

  • 添加您的代码。然后我们可以帮助您

标签: javascript node.js timeout


【解决方案1】:

另一种方法是利用child_process.exec 固有的timeout 参数。这个想法是将fs.read方法放在一个单独的文件中,并作为一个单独的shell进程从主进程执行。你可以这样做:

1- 创建一个read.js 脚本,其中包含:

var fs = require('fs');
fs.readFile('/etc/passwd', function (err, data) {
  if (err) throw err;
  process.send(data);
});

2- 在你的主脚本中,执行read.js,然后等待它的消息。

var exec = require('child_process').exec,
    child;

child = exec('node read.js',
  { timeout : 5000 }, //5 sec timeout
  function (error, stdout, stderr) {...}
});

child.on('message', function(data) {
  console.log(data);
});

【讨论】:

  • 我经常写作和阅读。我没有阅读整个文件,但感谢您的想法。
【解决方案2】:

正如其他人所提到的,您无法取消读取,因此您能做的最好的事情就是自己创建一个超时并在完成时丢弃结果。

fs.read(..., timeout(1000, function(err, result){

}));

function timeout(time, cb){
  var called = false;
  var timer = setTimeout(function(){
    // If the timer finishes before the function is called,
    // then run the callback with an error. 
    if (!called){
       called = true;
       cb(new Error("Function timed out."));
    }
  }, time);

  return function(){
    // If the read finishes before the timer, cancel the timer
    // and call the original callback.
    if (!called){
      clearTimeout(timer);
      called = true;
      cb.apply(this, arguments);
    }
  };
});

【讨论】:

  • 这是我已经尝试过的。它正在工作,但是“旧”读物会发生什么。它仍然挂在 Listening-Queue 中,不是吗?
  • 是的,旧读仍然存在并等待。如果读取超时,您可以关闭文件描述符并重新打开它。真的没有办法提前告诉你写的是否会有答案吗?似乎超时只能被解释为需要重新打开文件的错误。
  • 关闭文件描述符不起作用,读取仍然在后台挂起,参见上面的示例。有什么想法吗?
【解决方案3】:

您无法取消实际的读取操作。唯一的选择是设置一个计时器并从读取操作中取消订阅(使用 removeEventListener),然后通过调用带有自定义“超时”错误的原始事件处理程序继续。

希望这会有所帮助,如果您发布一些代码,我可以向您展示我将如何做到这一点。

【讨论】:

  • 对不起,我不明白如何使用 removeEventListener。
【解决方案4】:
var fs = require('fs');
var status = 0; // 0:start 1:fin
var timeout = 500;

fs.readFile('filename', function(err,data){
   status = 1
   console.log(data)
});

var timer = setTimeout(function(){
  clearTimeout(timer);
  if(!status){

    throw new Error('timeout');
  }
}, timeout);

【讨论】:

  • 这是我已经尝试过的。它正在工作,但是“旧”读物会发生什么。它仍然挂在 Listening-Queue 中,不是吗?
  • 我认为你可以尝试使用这个模块 seq-queue github.com/changchang/seq-queue
【解决方案5】:

对于不提供本机超时功能的函数(如 fs.stat、fs.read 等),您可以使用 callback-timeout 模块之类的东西包装回调。

你可以的

const timeout = require('callback-timeout');
const fs = require('fs');

fs.stat('/mnt/never-returns', timeout((err, stats)=>{
   if(err) throw err;
   //happy with stats
}, 2000, 'fs.stat did not return in 2 secs'));

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 2014-10-03
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2018-09-14
    • 2019-03-09
    • 2011-09-02
    • 2023-03-05
    相关资源
    最近更新 更多