【问题标题】:Node.js promises and error handling. Can this not be done cleaner?Node.js 承诺和错误处理。这不能做得更干净吗?
【发布时间】:2018-09-13 03:31:57
【问题描述】:

我是编写 node.js 的新手,并且遇到了一些杂乱代码的问题。不知道是不是乱码,可能我只是不习惯node代码吧。

无论如何,代码可以工作,但我对我的错误处理有点不确定,比如某些承诺失败时会发生什么。我尝试在 catch 步骤中进行回滚/释放,但我不确定这是否可以。

还有。这段代码能写得更干净吗?

function insertAnAddress(){ 
 var address = {
     country : "A country",
     city : "A city",
     street : "Random",
     number : 6,
     postalcode : "A789",
     province : "a province"
   }

  dbpool.getConnection( (err, connection) => {
       beginTransaction(connection)
          .then( () => {
                     return insertAddress(address,connection);
          })
         .then((rows) => {
                       console.log(rows);
               return commitTransaction(connection)
         })
         .then(()=>{
              connection.release();
              })
         .catch((err) => {
              //If rollback fails, the connection will not be released.
              //also, is it a good idea to try and do the rollback/release here in the catch?
              connection.rollback(() => {
                  connection.release();
              });
              throw err;
         });
    });
});


function beginTransaction(connection){
 return new Promise( (resolve, reject) => {
  connection.beginTransaction( (err) => {
    if (err) {reject(err);}
    resolve();
  })});
}


function insertAddress(address,connection) {
    return new Promise( (resolve, reject) => {
     // Do async job
        connection.query('INSERT INTO address (country,city,Street,number,postalcode,province) VALUES(?,?,?,?,?,?)', [address.country,'4','5',6,'7','8'] , (err, rows) => {
            if (err) {reject(err);}

            resolve(rows);

        })
    })
}

function commitTransaction(connection) {
  return new Promise( (resolve, reject) => {
   // Do async job
   connection.commit(function(err) {
      if (err) {reject(err);}
      resolve();
})})}

【问题讨论】:

标签: mysql node.js promise


【解决方案1】:

几个建议:

1) 使用util.promisify 将回调样式转换为Promise 样式,而不是Promise 构造函数

2) 当箭头函数由单个 return 语句组成时,去掉花括号和 return 关键字。

3) 使用finally 释放连接,无论是否有错误。

结果:

const util = require('util');

function insertAnAddress(){ 
 var address = {
     country : "A country",
     city : "A city",
     street : "Random",
     number : 6,
     postalcode : "A789",
     province : "a province"
   }

  dbpool.getConnection( (err, connection) => {
       beginTransaction(connection)
         .then( () => insertAddress(address,connection) )
         .then((rows) => {
               console.log(rows);
               return commitTransaction(connection);
         })
         .catch(util.promisify(connection.rollback.bind(connection)))
         .finally( () => connection.release() );
    });
});


function beginTransaction(connection){
 return util.promisify(connection.beginTransaction.bind(connection))();
}


function insertAddress(address,connection) {
    return util.promisify(connection.query.bind(connection))(
      'INSERT INTO address (country,city,Street,number,postalcode,province) VALUES(?,?,?,?,?,?)',
      [address.country,'4','5',6,'7','8']
    );
}

function commitTransaction(connection) {
  return util.promisify(connection.commit.bind(connection))();
}

您还可以通过使用包含mysql 库的库(如mysql-promise 或更好的IMO)来摆脱所有util.promisify 调用,方法是使用具有bluebird 的Promise 库promisifyAll功能。

【讨论】:

  • 请注意,promise.finally 仅受节点 10.0 支持或在 >=8.1.4 中使用 --harmony-promise-finally,除非他使用的是 Promise 库。
猜你喜欢
  • 1970-01-01
  • 2015-07-03
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2020-04-11
  • 1970-01-01
  • 2015-07-29
  • 1970-01-01
相关资源
最近更新 更多