如何在Node.js中异步/等待“ main”函数,该函数使用mysql查询将输出驱动到多个文件?

克里斯-j:

我想遍历员工列表,并将相关详细信息记录到单独的文件中。员工列表来自mysql,最终他们的详细信息来自对HR系统的请求。下面的代码,加上了logger.end的整体注释,可以正常工作,并且我创建了相关的员工日志。

/*
 *  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'
}

我已经阅读了很多关于promises和async / await的文章,但是似乎没有任何效果,因此我需要检查以确保我朝着正确的方向前进。

这是SQL;

CREATE TABLE employees
(forename varchar(40)
,surname varchar(40)
,employee_id integer
);

INSERT into employees values ('Fred', 'Flintstone', 1);
INSERT into employees values ('Wilma', 'Flintstone', 2);
INSERT into employees values ('Barney', 'Rubble', 3);
INSERT into employees values ('Betty', 'Rubble', 4);
richytong:

我很确定这与节点的异步性质有关

你是正确的。如果在结束流后尝试进行写入,则写入流将引发遇到的错误。查看您的代码,我看到有关执行顺序的合理假设是如何导致您的错误的。

conn.connect((err) => {...});

const mainResult = fnMain();

controlLogger.end();

乍一看,这很好。连接到数据库,在main中进行处理,然后结束流。但是,这实际上并不好,因为fnMain中发生了异步问题

function fnMain() {
    conn.query('...', (err, rows) => {
        ...
        for (const row of rows) {
            controlLogger.write(...);
        }
    })

}

nodejs不是很聪明;它既不知道查询何时完成,也不知道何时调用controlLogger.write。它所知道的就是您启动了数据库连接,开始了查询的执行,并立即结束了记录器的写流。从您当前的代码来看,事件的顺序是

  1. 创建mysql连接
  2. 开始查询
  3. 结束记录器写流
  4. 写到写流(查询完成后)

您遇到了错误,因为4现在在3之后发生了。修复程序正在移动这条线

controlLogger.end();

在最后一个controlLogger.write之后,就像这样:

controlLogger.write('END\r\n');
controlLogger.end();

这样可以确保您在完成最后一次写入后结束controlLogger写入流。

编辑:重构代码

/*
 *  40-mysql-2-fs.js
 *
 *  ---------------------------------------------------------------------
 *
 */
const fs = require('fs');
const { promisify } = require('util');

//File Write
const ctrlFileName = 'log41-EMP.txt';
const 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'
});

// new
const connect = connection => {
  return (promisify(connection.connect.bind(connection))()
    .then(() => console.log('Connection established!'))
    .catch(() => console.log('Error connecting to Db')))
};

const query = connection => {
  return promisify(connection.query.bind(connection))
};

const loopthruFileTest = async row => {
  const logFileName = 'log41-' + row.forename + '.txt';
  console.log('loopthruFileTest', logFileName)
  const logger = fs.createWriteStream(logFileName, { flags: 'a' })
  logger.write('Log: ' + logFileName + ' Surname: ' + row.surname + '\r\n');
  logger.end();
};

const closeConnection = connection => connection.end();

const fnMain = async () => {
  await connect(conn);
  const rows = await query(conn)('SELECT * FROM employees');
  console.log('Data received from Db:');
  let 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');
    await loopthruFileTest(row)
  }
  controlLogger.write('END\r\n');
  controlLogger.end();
  closeConnection(conn);
};

fnMain();

发生了什么变化:我从某些块中创建了函数,并使它们异步。我也做了fnMade异步,所以我可以等待我做的异步块。

本文收集自互联网,转载请注明来源。

如有侵权,请联系 [email protected] 删除。

编辑于
0

我来说两句

0 条评论
登录 后参与评论

相关文章

如何在Node.js中使用异步并正确等待?

如何使函数等待节点js中的异步函数解析?

使用Node.js在Cassandra中异步等待

即使等待位于 Node.js 中的异步函数中,如何修复“await 仅在异步函数中有效”?

Node.js异步/等待MySQL查询

如何在Node.js中显示异步函数的结果

如何在Node.js中处理异步函数

如何在Node.js中处理异步函数

Node js异步等待函数不会相互等待

异步中代码执行的顺序等待在Node.js中的函数中无法正常工作?

如何在Node.js中使用crypto.randomBytes使用异步/等待?

如何在Node.js上使用DynamoDb测试等待/异步?

Node.js 7如何在异步/等待中使用序列化事务?

Node.js:使用异步/等待时如何避免嵌套.then()

异步/等待-如何在递归Ajax函数中实现Javascript异步等待?

如何在嵌套的异步/等待函数中返回数据

如何在异步等待函数中返回值?

如何在react render函数中异步等待?

Node.js 使用 util 类函数等待异步

如何使用异步并等待节点js中的数据库中的选择

在node-js中异步/等待获取

在node.js中异步/等待理解

Node.js中的异步/等待行为

如何在Nuxt.js中使用异步等待?

异步并等待节点 js 中的 MySQL 调用

如何在Node.js或Javascript中将异步函数调用包装到同步函数中?

如何等待来自 golang wasm 的 js 异步函数?

在Node.JS中使用异步/等待正确请求

异步等待:即使一个错误,如何在多个等待调用中获取数据?