1

好吧,我似乎很难开始思考.. um.. 功能方式.. 或异步方式。

我对 node.js 比较陌生,但我在 c#、java、c++ 方面有多年的经验。

图片 我有简单的任务。这个任务的想法是每一行都应该在前一行完成之后执行(阻塞操作)。让我说,c# 中的正常方法。另外,(这就是这篇文章的原因)让我们假设我们的代码中有一个条件行。其伪代码如下:

f = OpenFile("aaa.txt")
If f.ReadLine(1) == "bbb" // read the first line
    line = f.ReadLine(2)  // read the second line
else
    line = ReadLine(3)    // read the third line
DataBase.Insert(line)     // store the line in some database, lets say in mysql
DeleteFile(f)

很简单。现在,据我了解,node.js 通过向几乎每个函数添加回调来使用非阻塞方法。这样一来,这个简单的任务对我来说似乎成了一场噩梦。如果我尝试重现上面的代码,它将如下所示:

OpenFile(f, function() {
    ReadLine(f, 1, function(line) {
        if line == "bbb" {
            ReadLine(f,2, function(line) {
                DataBase.Insert(line, function() {
                    DeleteFile(f);
                });
            });
        {
        else {
            ReadLine(f,3, function(line) {
                DataBase.Insert(line, function() { // the same again
                    DeleteFile(f);
                });
            });
        }
    });    

});

好吧,你明白了。在这个例子中,如果我需要确保只有在文件成功打开后才会读取该行,我需要在回调中编写“下一行的逻辑”。而且我应该只在“上一行回调”中继续写“下一行逻辑”。如果我不这样做,我可能会遇到这种情况,例如,我会尝试读取未打开的文件的行我还要注意,在我的实际代码中,我确实使用了非阻塞函数,例如:

jsdom.env(..)
fs.exec(..)

我在上面代码中的方法是否正确?或者我错过了什么,我的方法完全错误?我希望有更好的解决方案和方法。

感谢您的时间。

4

2 回答 2

2

您的方法似乎是正确的,这就是它的工作方式。你是对的,很难找到一种时尚的方式来编写异步代码。

处理此问题的一个工具是Step,它允许您定义一系列函数作为彼此的回调:

Step(
  function(...) {
    OpenFile...
  },
  function(...) {
    ReadLine(f, 2, this);
  },
  function(err, line) {
    if (err) throw err;
    if (line === "bbb")
      DataBase.Insert(line, this);
    else
      DataBase.Insert(line, this);
  },
  function(...) {
    DeleteFile...
  }
);

In Stepthis充当回调函数,并被给定序列中的以下函数替换。也可以触发并行任务。文档是直截了当的。

可能你更喜欢这种方式。


或者没有其他工具:

无需使用匿名函数作为回调。您可以定义一个函数并将其名称插入为回调,这样您就可以在不使用其他工具的情况下消除代码重复。小草稿:

OpenFile(f, function() {
    ReadLine(f, 1, function(line) {
        if line == "bbb" {
            ReadLine(f,2, insertIntoDatabaseAndDeleteFile);
        {
        else {
            ReadLine(f,3, insertIntoDatabaseAndDeleteFile);
        }
    });    

});

function insertIntoDatabaseAndDeleteFile(line, f) {
  DataBase.Insert(line, function() { 
      DeleteFile(f);
  });
}
于 2013-04-01T10:04:57.377 回答
1

作为一名长期的 C++ 开发人员,我可以告诉你:

a) 你的代码没问题 b) 你的感觉也没问题。c) 随着时间的推移,情况正在好转。与此同时,我觉得在 C++ 中调用同步 io 函数真的很不舒服

这是您的代码的另一个版本,它给您一个印象,您可以在 JS 中做什么:

OpenFile(f, function() {
    var myReadInsDel = function( f, n, callback ) {
        ReadLine(f,3, function( line ) {
            DataBase.Insert( line, function() {
                DeleteFile( f, callback );
            });
    });
    ReadLine(f, 1, function(line) {
        if line == "bbb" {
            myReadInsDel( f, 2 ); // you could provide also a callback here
        }
        else {
            myReadInsDel( f, 3 ); // you could provide also a callback here
        }
    });    
});
于 2013-04-02T07:10:25.147 回答