Nodejs Async的使用,为何这样写实现不了顺序执行?
Nodejs Async的使用,为何这样写实现不了顺序执行?
async.series(
[
function(callback){
writeLog(callback);
},
function(callback){
readLog(callback);
},
function(callback){
funcEnd(res, callback);
}
]
);
想顺序执行这三个方法,但是总是并发执行,是不是哪里写的不对呢?
function writeLog(callback){
fs.openSync(qpage,'w',0666);
for (var i = 1; i <= cnt; i++ ) {
client.hgetall(i, function(err, obj) {
fs.appendFileSync(qpage, "<br />" +util.inspect(obj), encoding='utf8');
});
}
callback(null);}
function readLog(callback){
query = fs.readFileSync(qpage, 'utf8');
callback(null);}
function funcEnd(res, callback){
res.end(query, 'utf8');
callback(null);}
在Node.js中使用async
库进行异步操作时,如果想要确保函数按顺序执行,必须确保每个函数在完成其任务后正确地调用回调函数。从你提供的代码来看,问题在于writeLog
函数中的异步操作(fs.appendFileSync
)没有正确处理,导致callback
被提前调用。
示例代码
const async = require('async');
const fs = require('fs');
const util = require('util');
// 假设client是一个已经定义好的客户端对象
const client = {}; // 请根据实际情况替换
const qpage = 'log.txt';
const cnt = 5;
function writeLog(callback) {
fs.open(qpage, 'w', 0o666, (err, fd) => {
if (err) return callback(err);
const write = () => {
if (cnt > 0) {
client.hgetall(cnt, (err, obj) => {
if (err) return callback(err);
fs.appendFile(fd, `<br />${util.inspect(obj)}`, (err) => {
if (err) return callback(err);
cnt--;
write(); // 递归调用直到所有数据都写入
});
});
} else {
fs.close(fd, (err) => {
if (err) return callback(err);
callback(null); // 所有操作完成后调用callback
});
}
};
write();
});
}
function readLog(callback) {
fs.readFile(qpage, 'utf8', (err, data) => {
if (err) return callback(err);
query = data;
callback(null);
});
}
function funcEnd(res, callback) {
res.end(query, 'utf8');
callback(null);
}
async.series([
(callback) => writeLog(callback),
(callback) => readLog(callback),
(callback) => funcEnd(res, callback)
]);
解释
- 异步操作:
writeLog
函数中,fs.appendFile
是一个异步操作,不能直接使用同步版本fs.appendFileSync
,因为它会阻塞事件循环。 - 递归写入:为了确保所有的
hgetall
操作都完成后再关闭文件描述符,我们使用递归来处理每次的写入操作。 - 顺序执行:通过将每个异步操作封装在一个函数中,并在该函数中调用
callback
来通知async.series
该操作已完成,从而保证了操作的顺序执行。
以上代码确保了writeLog
、readLog
和funcEnd
这三个函数能够按顺序执行。
你的业务代码都是同步执行的啊
仅仅几个需求是,毕竟还是因为并发才选择的Node
目测没什么问题。。。。应该是顺序执行的吧
哦,发现一个问题了 client.hgetall,这个是异步的还是同步的?如果是异步的话, 就会有问题
你的问题在于writeLog
函数中的client.hgetall
操作是异步的,但你使用的是fs.openSync
和fs.appendFileSync
这两个同步的方法。async.series
确实可以保证函数按顺序调用,但由于writeLog
内部的异步操作(client.hgetall
),writeLog
的callback
可能在所有异步操作完成之前就被调用了。
为了确保writeLog
内的异步操作完成后再调用callback
,你可以使用async.each
或返回一个Promise来处理。以下是使用回调风格改写的示例:
const async = require('async');
async.series([
function(callback) {
writeLog(callback);
},
function(callback) {
readLog(callback);
},
function(callback) {
funcEnd(res, callback);
}
]);
function writeLog(callback) {
fs.open(qpage, 'w', 0o666, (err, fd) => {
if (err) return callback(err);
let i = 1;
const nextIteration = () => {
if (i > cnt) return callback(null);
client.hgetall(i++, (err, obj) => {
if (err) return callback(err);
fs.appendFile(fd, "<br />" + util.inspect(obj), 'utf8', err => {
if (err) return callback(err);
nextIteration();
});
});
};
nextIteration();
});
}
function readLog(callback) {
fs.readFile(qpage, 'utf8', (err, data) => {
if (err) return callback(err);
query = data;
callback(null);
});
}
function funcEnd(res, callback) {
res.end(query, 'utf8');
callback(null);
}
这里writeLog
函数中通过递归方式确保每个hgetall
操作完成后才继续下一个迭代。这样可以保证callback
只在所有异步操作完成后被调用,从而保证async.series
中其他函数按顺序执行。