理解`nodejs`asynchronous文件读取

我想了解nodejsasynchronous行为。 考虑

 ### 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. 

我该如何解决? 完成这样一个任务的最习惯的方法是什么?

更新:我想在这里注意到,我不想使用readFileSyncasync (至less现在,至less)。 现在,我想了解用普通的JS来做到这一点的正确方法,并在此过程中更好地理解asynchronous编程。

你实质上要求做的是在逐行迭代之前等待一个asynchronous操作readFile(found[1])完成,然后再继续下一行。 由于这是一个asynchronous操作,它不会暂停您的JavaScript执行。 因为它不会暂停执行,所以.forEach()的其余部分继续运行,并且readFile(found[1])的结果与正在发生的其他事情交织在一起。

这样的问题的唯一解决scheme是对迭代进行更多的控制,以便下一次迭代线不会继续,直到完成当前迭代。 您将不得不停止使用.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); });