Warning: file_get_contents(/data/phpspider/zhask/data//catemap/8/python-3.x/16.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
如何异步/等待a";“主要”;函数,它使用mysql查询将输出驱动到多个文件?_Mysql_Node.js_Async Await - Fatal编程技术网

如何异步/等待a";“主要”;函数,它使用mysql查询将输出驱动到多个文件?

如何异步/等待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

我想循环浏览员工列表,并将相关详细信息记录到单独的文件中。 员工名单来自mysql,最终他们的详细信息将来自对人力资源系统的请求。 下面的代码,注释掉了totallogger.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'
}

我认为,由于异步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。它只知道您启动了数据库连接,开始执行查询,并立即结束了记录器写入流。根据当前代码,事件的顺序是

  • 创建mysql连接
  • 启动查询
  • 结束记录器写入流
  • 写入到写入流(查询完成后)
  • 您遇到了错误,因为现在4发生在3之后。修理工正在移动这条线

    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();
    })