如何异步/等待a";“主要”;函数,它使用mysql查询将输出驱动到多个文件?
我想循环浏览员工列表,并将相关详细信息记录到单独的文件中。 员工名单来自mysql,最终他们的详细信息将来自对人力资源系统的请求。 下面的代码,注释掉了totallogger.end,运行正常,我创建了相关的员工日志如何异步/等待a";“主要”;函数,它使用mysql查询将输出驱动到多个文件?,mysql,node.js,async-await,Mysql,Node.js,Async Await,我想循环浏览员工列表,并将相关详细信息记录到单独的文件中。 员工名单来自mysql,最终他们的详细信息将来自对人力资源系统的请求。 下面的代码,注释掉了totallogger.end,运行正常,我创建了相关的员工日志 /* * 40-mysql-2-fs.js * * --------------------------------------------------------------------- * */ var fs = require('fs'); //File W
/*
* 40-mysql-2-fs.js
*
* ---------------------------------------------------------------------
*
*/
var fs = require('fs');
//File Write
const ctrlFileName = 'log41-EMP.txt';
var controlLogger = fs.createWriteStream(ctrlFileName, {
flags: 'a' // 'a' means appending (old data will be preserved)
});
//mySQL
const mysql = require('mysql');
const conn = mysql.createConnection({
host: 'localhost',
user: 'myuser',
password: 'mypasswd',
database: 'mydb'
});
conn.connect((err) => {
if(err){
console.log('Error connecting to Db');
return;
}
console.log('Connection established!');
});
const mainResult = fnMain();
//controlLogger.end();
conn.end();
function fnMain() {
conn.query('SELECT * FROM employees',
(err,rows) => {
if(err) throw err;
console.log('Data received from Db:');
var msg_no = 1;
for (const row of rows) {
console.log(msg_no,"-", row.forename,"#",row.surname);
controlLogger.write(msg_no + '-' + row.forename + '#' + row.surname + '\r\n');
var loopResult = loopthruFileTest(row);
msg_no++;
}
controlLogger.write('END\r\n');
});
}
function loopthruFileTest(row) {
logFileName = 'log41-'+row.forename+'.txt';
console.log('loopthruFileTest ',logFileName);
//File Write
var logger = fs.createWriteStream(logFileName, {
flags: 'a' // 'a' means appending (old data will be preserved)
});
logger.write('Log: ' + logFileName + ' Surname: ' + row.surname + '\r\n');
logger.end();
}
如果我取消注释controlLogger.end(),我会得到以下错误代码>
我很确定这与节点的异步性质有关
/home/ec2-user/AWS/r2data-index/03-load-transactions-pool/node_modules/mysql/lib/protocol/Parser.js:437
throw err; // Rethrow non-MySQL errors
^
Error [ERR_STREAM_WRITE_AFTER_END]: write after end
at writeAfterEnd (_stream_writable.js:265:14)
at WriteStream.Writable.write (_stream_writable.js:314:5)
at Query.<anonymous> (/home/ec2-user/AWS/r2data-index/03-load-transactions-pool/40-mysql-2-fs.js:47:27)
at Query.<anonymous> (/home/ec2-user/AWS/r2data-index/03-load-transactions-pool/node_modules/mysql/lib/Connection.js:526:10)
at Query._callback (/home/ec2-user/AWS/r2data-index/03-load-transactions-pool/node_modules/mysql/lib/Connection.js:488:16)
at Query.Sequence.end (/home/ec2-user/AWS/r2data-index/03-load-transactions-pool/node_modules/mysql/lib/protocol/sequences/Sequence.js:83:24)
at Query._handleFinalResultPacket (/home/ec2-user/AWS/r2data-index/03-load-transactions-pool/node_modules/mysql/lib/protocol/sequences/Query.js:149:8)
at Query.EofPacket (/home/ec2-user/AWS/r2data-index/03-load-transactions-pool/node_modules/mysql/lib/protocol/sequences/Query.js:133:8)
at Protocol._parsePacket (/home/ec2-user/AWS/r2data-index/03-load-transactions-pool/node_modules/mysql/lib/protocol/Protocol.js:291:23)
at Parser._parsePacket (/home/ec2-user/AWS/r2data-index/03-load-transactions-pool/node_modules/mysql/lib/protocol/Parser.js:433:10)
Emitted 'error' event on WriteStream instance at:
at errorOrDestroy (internal/streams/destroy.js:108:12)
at writeAfterEnd (_stream_writable.js:267:3)
at WriteStream.Writable.write (_stream_writable.js:314:5)
[... lines matching original stack trace ...]
at Protocol._parsePacket (/home/ec2-user/AWS/r2data-index/03-load-transactions-pool/node_modules/mysql/lib/protocol/Protocol.js:291:23) {
code: 'ERR_STREAM_WRITE_AFTER_END'
}
我认为,由于异步node.js事件循环,您的fnMain()函数在con.connect()函数完成之前执行。另外,conn.end()函数没有等待fnMain()解析,而是在sql查询执行之前关闭db连接,这就是它抛出结束后写入错误的原因
var fs = require('fs');
//File Write
const ctrlFileName = 'log41-EMP.txt';
let controlLogger;
const loopthruFileTest = async row => {
const logFileName = 'log41-'+row.forename+'.txt';
console.log('loopthruFileTest ',logFileName);
//File Write
var logger = await fs.createWriteStream(logFileName, {
flags: 'a' // 'a' means appending (old data will be preserved)
});
await logger.write('Log: ' + logFileName + ' Surname: ' + row.surname + '\r\n');
logger.end();
return row
}
const db = mysql.createConnection({
host: 'localhost',
user: 'myuser',
password: 'mypasswd',
database: 'mydb'
});
const fnMain = () => new Promise((res) => {
//connect to the database
res(db.connect())
})
.then(async () => {
//establish the control logger
controlLogger = await fs.createWriteStream(ctrlFileName, {
flags: 'a' // 'a' means appending (old data will be preserved)
});
return
})
.catch(e => {
console.log('Error connecting to Db');
})
.then(()=> {
console.log('Connection established!');
return db.query('SELECT * FROM employees')
})
.then(rows => {
console.log('Data received from Db:');
//map rows into promises and resolve all
return Promise.All(rows.map((row, rowIndex) => new Promise((res) => {
console.log(rowIndex,"-", row.forename,"#",row.surname);
controlLogger.write(rowIndex + '-' + row.forename + '#' + row.surname + '\r\n');
res(loopthruFileTest(row))
})
))
})
.then(resultArray => {
controlLogger.write('END\r\n');
})
.finally(() => {
// .finally() will always execute even if there are uncaught errors in the promise chain
controlLogger.end();
db.end();
})
我很确定这与节点的异步性质有关
你说得对。如果在结束流后尝试写入,写入流将抛出遇到的错误。查看您的代码,我看到了关于执行顺序的合理假设是如何导致错误的
conn.connect((err)=>{…});
const main result=fnMain();
controlLogger.end();
乍一看,这很好。连接到数据库,在main中执行一些操作,然后结束流。然而,这实际上并不好,因为fnMain中存在异步内容
函数fnMain(){
conn.query(“…”,(错误,行)=>{
...
for(常量行中的行){
controlLogger.write(…);
}
})
}
nodejs不是很聪明;它不知道何时完成查询,也不知道何时调用controlLogger.write。它只知道您启动了数据库连接,开始执行查询,并立即结束了记录器写入流。根据当前代码,事件的顺序是
controlLogger.end();
在最后一个controlLogger.write之后,如下所示:
controlLogger.write('END\r\n');
controlLogger.end();
这保证您在完成最后一次写入后结束controlLogger写入流
编辑:稍微重构代码
/*
*40-mysql-2-fs.js
*
* ---------------------------------------------------------------------
*
*/
常数fs=要求('fs');
const{promisify}=require('util');
//文件写入
const-ctrlFileName='log41 EMP.txt';
const controlLogger=fs.createWriteStream(ctrlFileName{
标志:“a'/'a'表示追加(将保留旧数据)
});
//mySQL
const mysql=require('mysql');
const conn=mysql.createConnection({
主机:“localhost”,
用户:“myuser”,
密码:“mypasswd”,
数据库:“mydb”
});
//新的
const connect=连接=>{
返回(promisify(connection.connect.bind(connection))()
.then(()=>console.log('建立连接!'))
.catch(()=>console.log('Error connecting to Db'))
};
const query=connection=>{
返回promisify(connection.query.bind(connection))
};
const loopthruFileTest=异步行=>{
常量logFileName='log41-'+row.forename+'.txt';
console.log('loopthruFileTest',logFileName)
const logger=fs.createWriteStream(日志文件名,{flags:'a'})
logger.write('Log:'+logFileName+'姓氏:'+row.name+'\r\n');
结束();
};
const closeConnection=connection=>connection.end();
const fnMain=async()=>{
等待连接(conn);
const rows=等待查询(conn)('SELECT*FROM employees');
log('从数据库接收的数据:');
设msg_no=1;
for(常量行中的行){
日志(msg_no,'-',row.forename,'.',row.name);
controlLogger.write(msg_no+'-'+row.forename+'#'+row.namite+'\r\n');
等待loopthruFileTest(行)
}
controlLogger.write('END\r\n');
controlLogger.end();
闭合连接(conn);
};
fnMain();
改变之处:我用某些块创建了函数,并使它们异步。我还制作了FNMAKE ASSYNC,以便我可以等待我制作的异步块。您好,感谢您的回复,根据我的理解,您对正在发生的事情是正确的,但是我添加了fnMain,因为我试图处理“等待”conn.query和LOOPTHURFILETEST,在此之前,controlLogger.end紧跟在写入之后。
conn.query
本身是不可等待的;但是,如果您使用的是node,则可以使用它们的一个实用程序const{promisify}=require('util')
。然后您可以像这样等待conn.query:const rows=await promisify(conn.query.bind(conn))
关于loopthruFileTest,它似乎是完全同步的,所以不需要等待itcorrection:const rows=await promisify(conn.query.bind(conn))('SELECT…)
很高兴了解promisify'ing查询,正如我简要提到的loopthruFileTest只是请求子函数的占位符!嗨,这看起来像我要找的但是。。。我得到以下错误,我无法通过它<代码>/home/ec2 user/AWS/r2 data index/03 load transactions pool/42 stackoverflow answers.js:56})^SyntaxError:missing)在模块的wrapSafe(internal/modules/cjs/loader.js:1070:16)的参数列表之后。在Object.Module.处编译(internal/modules/cjs/loader.js:1120:27)。扩展名在Module.load(内部/modules/cjs/loader.js:1000:32)在Function.Module._load(内部/modules/cjs/loader.js:899:14)@chris-j是的,对不起,我可能应该在提交答案之前在代码编辑器中测试一下。它只是在承诺之后少了一个“)”而已。代码h
var fs = require('fs');
//File Write
const ctrlFileName = 'log41-EMP.txt';
let controlLogger;
const loopthruFileTest = async row => {
const logFileName = 'log41-'+row.forename+'.txt';
console.log('loopthruFileTest ',logFileName);
//File Write
var logger = await fs.createWriteStream(logFileName, {
flags: 'a' // 'a' means appending (old data will be preserved)
});
await logger.write('Log: ' + logFileName + ' Surname: ' + row.surname + '\r\n');
logger.end();
return row
}
const db = mysql.createConnection({
host: 'localhost',
user: 'myuser',
password: 'mypasswd',
database: 'mydb'
});
const fnMain = () => new Promise((res) => {
//connect to the database
res(db.connect())
})
.then(async () => {
//establish the control logger
controlLogger = await fs.createWriteStream(ctrlFileName, {
flags: 'a' // 'a' means appending (old data will be preserved)
});
return
})
.catch(e => {
console.log('Error connecting to Db');
})
.then(()=> {
console.log('Connection established!');
return db.query('SELECT * FROM employees')
})
.then(rows => {
console.log('Data received from Db:');
//map rows into promises and resolve all
return Promise.All(rows.map((row, rowIndex) => new Promise((res) => {
console.log(rowIndex,"-", row.forename,"#",row.surname);
controlLogger.write(rowIndex + '-' + row.forename + '#' + row.surname + '\r\n');
res(loopthruFileTest(row))
})
))
})
.then(resultArray => {
controlLogger.write('END\r\n');
})
.finally(() => {
// .finally() will always execute even if there are uncaught errors in the promise chain
controlLogger.end();
db.end();
})