Node.js 理解'nodejs'异步文件读取

Node.js 理解'nodejs'异步文件读取,node.js,Node.js,我试图理解nodejs的异步行为。考虑 ### text file: a.txt ### 1. Lorem ipsum dolor sit amet, consectetur adipiscing elit. {{b.txt}} 3. Donec et mollis dolor. {{c.txt}} ######################## ### text file: b.txt ### 2. Donec a diam lectus. Sed sit amet ipsum maur

我试图理解nodejs的异步行为。考虑

### text file: a.txt ###
1. Lorem ipsum dolor sit amet, consectetur adipiscing elit. 
{{b.txt}}
3. Donec et mollis dolor.
{{c.txt}}
########################

### text file: b.txt ###
2. Donec a diam lectus. Sed sit amet ipsum mauris.
########################


### text file: c.txt ###
4. Maecenas congue ligula ac quam viverra nec consectetur ante hendrerit. 
########################

var readFile = function(file) {
    fs.readFile(file, "utf8", function (err, file_content) {
        if (err) console.log("error: " + err);

        file_content.split(/\n/)
            .forEach(function(line) {
                var found = line.match(/\{\{(.*?)\}\}/);
                found ? readFile(found[1]) : console.log(line);
            });
    });
};
我想要的输出是

1. Lorem ipsum dolor sit amet, consectetur adipiscing elit. 
2. Donec a diam lectus. Sed sit amet ipsum mauris.
3. Donec et mollis dolor.
4. Maecenas congue ligula ac quam viverra nec consectetur ante hendrerit. 
我得到的输出是

1. Lorem ipsum dolor sit amet, consectetur adipiscing elit. 
3. Donec et mollis dolor.
2. Donec a diam lectus. Sed sit amet ipsum mauris.
4. Maecenas congue ligula ac quam viverra nec consectetur ante hendrerit. 
我该如何解决这个问题?完成这项任务最惯用的方法是什么


更新:我想在这里指出,我不想使用
readFileSync
async
(至少现在是这样)。现在,我想了解使用纯JS实现这一点的正确方法,并在此过程中更好地理解异步编程。

您本质上要求做的是让逐行迭代等待异步操作
readFile(找到[1])
完成,然后再继续下一行。因为它是一个异步操作,所以不会暂停Javascript执行。因为它不会暂停执行,所以
.forEach()
的其余部分将继续运行,并且
读取文件(找到[1])
的结果将与正在进行的所有其他内容交织在一起

对于这样的问题,唯一的解决方案是对迭代进行更多的控制,以便在完成对当前行的处理之前,行的下一次迭代不会继续。您必须停止使用
.forEach()
,并进行手动迭代

以下是关于如何使用手动迭代使函数工作的一般想法:

var readFile = function(file, done) {
    fs.readFile(file, "utf8", function (err, file_content) {
        if (err) {
            console.log("error: ", err);
            done(err);
            return;
        }

        var lines = file_content.split(/\n/);
        var cntr = 0;

        function nextLine() {
            var found, line, more = false;
            while (cntr < lines.length) {
                line = lines[cntr++];
                found = line.match(/\{\{(.*?)\}\}/);
                if (found) {
                    readFile(found[1], function(err) {
                        if (err) {
                            return done(err);
                        }
                        nextLine();
                    });
                    more = true;
                    // break out of the while loop and let this function finish
                    // it will get called again when the async operation completes
                    break;
                } else {
                    console.log(line);
                }
            }
            // if we're all done, then call the callback to 
            // to tell the caller we're done with all async stuff
            if (!more) {
                done(null);
            }
        }
        // start the first iteration
        nextLine();
    });
};

// call it initially like this
readFile("somefile.text", function(err) {
    if (err) console.log(err);
});
var readFile=函数(文件,完成){
读取文件(文件“utf8”,函数(错误,文件内容){
如果(错误){
log(“错误:”,err);
完成(错误);
返回;
}
var lines=文件内容.split(/\n/);
var-cntr=0;
函数nextLine(){
找到的var,行,更多=假;
while(cntr
您可以使用readFileSync或使用async库来实现此目的。谢谢您的评论,但我不想使用
readFileSync
async
(至少现在是这样)。现在,我想了解使用纯JS的正确方法。您的评论很有意义。你能给我举个例子,说明我到底是如何进行手动迭代的吗?谢谢@jfriend00的代码。这很有帮助。我要做的唯一编辑是添加
'var done=function(err){if(err)console.log(err);return;}到代码。@punkish-变量
done
是传递到
readFile()
的内容。这取决于原始调用方将函数传递给它,以便它可以知道何时全部完成。最后我添加了一个例子。