在Node.js中的字数计数例子中的closures的必要性

在Node.js in Action一书中,有一个例子,其中“./text”目录中的文件受字数限制。 我想问问,封闭使用是否实际上或只是一个风格的问题。 代码如下:

var fs = require('fs'); var completedTasks = 0; var tasks = []; var wordCounts = {}; var filesDir = './text'; function checkIfComplete() { completedTasks++; if (completedTasks == tasks.length) { for (var index in wordCounts) { console.log(index + ': ' + wordCounts[index]); } } } function countWordsInText(text) { var words = text .toString() .toLowerCase() .split(/\W+/) .sort() for (var index in words) { var word = words[index]; if (word) { wordCounts[word] = (wordCounts[word]) ? wordCounts[word] + 1 : 1; } } } // My question is on the use of closure below fs.readdir(filesDir, function(err, files) { if (err) throw err; for (var index in files) { var task = (function(file) { return function() { fs.readFile(file, function(err, text) { if (err) throw err; countWordsInText(text); checkIfComplete(); }); } })(filesDir + '/' + files[index]); tasks.push(task); } for (var task in tasks) { tasks[task](); } }); 

本书使用此代码来演示并行控制stream程的本质。 我的问题是为什么代码要经过这个看似扭曲的阐述(抱歉,大声笑,这里是一个新手)构build封闭,然后打电话给他们? (我指的是任务中的每个任务。)

这与我看来更自然吗?

 fs.readdir(filesDir, function(err, files) { if (err) throw err; tasks = files; // Just to make sure the check for completion runs fine. for (var index in files) { var file = files[index]; fs.readFile(filesDir + '/' + file, function(err, text) { if (err) throw err; countWordsInText(text); checkIfComplete(); }); } }); 

它不会像以前的代码那样是asynchronous和“并行”吗?

这里可以避免closures。 闭包将被要求避免臭名昭着的闭环 fs.readFile如果callback传递给fs.readFile访问循环variables或从其派生的东西, 将会发生。 因为那么在callback被调用的时候,循环variables的值就是分配给它的最后一个值。

你做的方式是可以的。 我没有试图彻底清除代码或使其具有适应性,但我会:

 var fs = require('fs'); var wordCounts = Object.create(null); var filesDir = './text'; function countWordsInText(text) { var words = text .toString() .toLowerCase() .split(/\W+/) .sort(); for (var index in words) { var word = words[index]; if (word) { wordCounts[word] = (wordCounts[word]) ? wordCounts[word] + 1 : 1; } } } fs.readdir(filesDir, function(err, files) { if (err) throw err; var total = files.length; var completedTasks = 0; for (var index in files) { fs.readFile(filesDir + '/' + files[index], function(err, text) { if (err) throw err; countWordsInText(text); completedTasks++; if (completedTasks === total) { for (var index in wordCounts) { console.log(index + ': ' + wordCounts[index]); } } }); } });