如何在异步操作中指示 "doneness"
How to indicate "doneness" in an async operation
鉴于此代码计算给定目录和子目录中的文件,我该如何指示操作已完成?
function walkDirs(dirPath) {
var fs = require('fs'),
path = require('path'),
events = require('events'),
count = 0,
emitter = new events.EventEmitter();
function walkDir(dirPath) {
function readDirCallback(err, entries) {
for (var idx in entries) {
var fullPath = path.join(dirPath, entries[idx]);
(function statHandler(fullPath) {
fs.stat(fullPath, function statEach(err, stats) {
if (stats) {
if (stats.isDirectory()) {
walkDir(fullPath);
} else if (stats.isFile()) {
count += 1;
emitter.emit('counted', count, fullPath);
}
}
});
})(fullPath);
}
}
fs.readdir(dirPath, readDirCallback);
}
walkDir(dirPath);
return emitter;
}
var walker = walkDirs('C:');
具体试过了,
- 在我认为合适的地方触发一个事件以指示 "doneness",特别是在
fs.readdir(dirPath, readDirCallback)
调用之后。
- 将
statHandler()
修改为 return 添加的计数。 (我意识到这实际上与在该函数内递增 count
没有什么不同。
这两个都失败了,因为检查时,count
的值为0。我确定我没有等到操作(计算文件)完成。显然,我需要在完成后触发回调或事件以获得正确的计数。
我知道代码计数成功,因为附加调试器时,计数值符合预期。
在这一点上,我相当肯定地确定我不知道如何进一步进行。特别是 -
如何在异步操作中实现指示"doneness"?
您可以通过使用承诺来实现这一点。在这个例子中我选择了Q.
npm install q
只要您考虑通过调用 .resolve()
函数来完成异步函数,您就兑现了您的承诺。当您的承诺得到解决时,它将在您的承诺对象 walkDirs
的 then .then()
函数中调用您的成功回调。每当您的承诺得到解决或拒绝时, .then()
函数就会被触发。如果您拒绝,您承诺将调用错误回调。
var q = require('q');
function walkDirs(dirPath) {
var deffered = q.defer();
var fs = require('fs'),
path = require('path'),
events = require('events'),
count = 0,
emitter = new events.EventEmitter();
function walkDir(dirPath) {
function readDirCallback(err, entries) {
for (var idx in entries) {
var fullPath = path.join(dirPath, entries[idx]);
(function statHandler(fullPath) {
fs.stat(fullPath, function statEach(err, stats) {
if (stats) {
if (stats.isDirectory()) {
walkDir(fullPath);
} else if (stats.isFile()) {
count += 1;
emitter.emit('counted', count, fullPath);
deffered.resolve(emitter); // resolve promise
}
}
});
})(fullPath);
}
}
fs.readdir(dirPath, readDirCallback);
}
walkDir(dirPath);
return q.promise;
}
walkDirs('C:')
.then(success, error) //can also take error callback if promise is rejected.
function success(function(data) {
//data = resolved data.
console.log("is successfully done");
})
function errer(function() {
console.log("is errorly done");
})
异步Javascript函数一般在完成时调用回调函数。在这种情况下,如果您有其他事件,done
事件将是合适的。 Promises 现在通常比回调更受青睐,但您确实需要先了解回调。
由于 readdir 是异步的,因此在下一行执行并不意味着它已完成。这就是异步代码与同步代码相比令人困惑的地方。如果我是你,我会使用调试器并逐步完成一些非常简单(比这更简单)的异步示例。确实需要一段时间才能习惯,而且很棘手。
有关步行目录,请参阅 https://www.npmjs.com/package/walk。你不想在这里重新发明轮子。始终确保 Google and/or 在 npmjs 上搜索现有模块。
一旦你确定你真的理解了回调和异步代码,那么你就可以继续学习 async
模块,然后,使用 bluebird
的 promises,ES6 promises 等等。像这样的 https://www.npmjs.com/package/co 可能会有用。
鉴于此代码计算给定目录和子目录中的文件,我该如何指示操作已完成?
function walkDirs(dirPath) {
var fs = require('fs'),
path = require('path'),
events = require('events'),
count = 0,
emitter = new events.EventEmitter();
function walkDir(dirPath) {
function readDirCallback(err, entries) {
for (var idx in entries) {
var fullPath = path.join(dirPath, entries[idx]);
(function statHandler(fullPath) {
fs.stat(fullPath, function statEach(err, stats) {
if (stats) {
if (stats.isDirectory()) {
walkDir(fullPath);
} else if (stats.isFile()) {
count += 1;
emitter.emit('counted', count, fullPath);
}
}
});
})(fullPath);
}
}
fs.readdir(dirPath, readDirCallback);
}
walkDir(dirPath);
return emitter;
}
var walker = walkDirs('C:');
具体试过了,
- 在我认为合适的地方触发一个事件以指示 "doneness",特别是在
fs.readdir(dirPath, readDirCallback)
调用之后。 - 将
statHandler()
修改为 return 添加的计数。 (我意识到这实际上与在该函数内递增count
没有什么不同。
这两个都失败了,因为检查时,count
的值为0。我确定我没有等到操作(计算文件)完成。显然,我需要在完成后触发回调或事件以获得正确的计数。
我知道代码计数成功,因为附加调试器时,计数值符合预期。
在这一点上,我相当肯定地确定我不知道如何进一步进行。特别是 -
如何在异步操作中实现指示"doneness"?
您可以通过使用承诺来实现这一点。在这个例子中我选择了Q.
npm install q
只要您考虑通过调用 .resolve()
函数来完成异步函数,您就兑现了您的承诺。当您的承诺得到解决时,它将在您的承诺对象 walkDirs
的 then .then()
函数中调用您的成功回调。每当您的承诺得到解决或拒绝时, .then()
函数就会被触发。如果您拒绝,您承诺将调用错误回调。
var q = require('q');
function walkDirs(dirPath) {
var deffered = q.defer();
var fs = require('fs'),
path = require('path'),
events = require('events'),
count = 0,
emitter = new events.EventEmitter();
function walkDir(dirPath) {
function readDirCallback(err, entries) {
for (var idx in entries) {
var fullPath = path.join(dirPath, entries[idx]);
(function statHandler(fullPath) {
fs.stat(fullPath, function statEach(err, stats) {
if (stats) {
if (stats.isDirectory()) {
walkDir(fullPath);
} else if (stats.isFile()) {
count += 1;
emitter.emit('counted', count, fullPath);
deffered.resolve(emitter); // resolve promise
}
}
});
})(fullPath);
}
}
fs.readdir(dirPath, readDirCallback);
}
walkDir(dirPath);
return q.promise;
}
walkDirs('C:')
.then(success, error) //can also take error callback if promise is rejected.
function success(function(data) {
//data = resolved data.
console.log("is successfully done");
})
function errer(function() {
console.log("is errorly done");
})
异步Javascript函数一般在完成时调用回调函数。在这种情况下,如果您有其他事件,done
事件将是合适的。 Promises 现在通常比回调更受青睐,但您确实需要先了解回调。
由于 readdir 是异步的,因此在下一行执行并不意味着它已完成。这就是异步代码与同步代码相比令人困惑的地方。如果我是你,我会使用调试器并逐步完成一些非常简单(比这更简单)的异步示例。确实需要一段时间才能习惯,而且很棘手。
有关步行目录,请参阅 https://www.npmjs.com/package/walk。你不想在这里重新发明轮子。始终确保 Google and/or 在 npmjs 上搜索现有模块。
一旦你确定你真的理解了回调和异步代码,那么你就可以继续学习 async
模块,然后,使用 bluebird
的 promises,ES6 promises 等等。像这样的 https://www.npmjs.com/package/co 可能会有用。