avatar
fireworks99
keep hungry keep foolish

NodeJS asynchronous request about MySQL

Description

NodeJS连接mysql数据库的请求是异步操作。现有客户想要注册,NodeJS需要连接数据库,查询用户表,若用户表中无此用户名方予以注册,否则拒绝。很明显,我需要获取查询的结果之后来决定是否将注册信息写入数据库,“查询”与“写入”这两个异步操作有明显的先后顺序,需要“回调”,用ES6的Promise能更好地解决这一问题。

当我没意识到异步操作时

const connection = require("./connect.js")

module.exports = function (username, password, callback) {

  connection.query('use blogs', function (err, res) {
    if(err) throw err;
    console.log("Database changed : " + res);
  })

  let flag = false;
  connection.query('select * from users', function (err, res) {
    if(err) throw err;

    let len = res.length;
    for(let i = 0; i < len; ++i) {
      if(res[i].username === username) {
        callback('The username was registered!');
        flag = true;
        break;
      }
    }
  })

  console.log(flag);

  if(flag === false) {
    const sql = 'insert into users(username, password) values("' + username + '", "' + password + '")'

    connection.query(sql, function (err, res) {
      if(err) throw err;
      console.log("Succeed : " + res);
    })
  }
}

上述代码console.log(flag)最先执行,然后“写入”操作很有可能先于“查询”操作

Promise

const connection = require("./connect.js")

module.exports = function (username, password) {

  new Promise((resolve, reject) => {
    connection.query('use blogs', function (err) {
      if(err) reject(err);
      else resolve('Database changed!')
    })
  }).then(function (info) {

    console.log(info);// Database changed!

    return  new Promise((resolve, reject) => {

      connection.query('select * from users', function (err, res) {
        if(err) reject(err);
        else {
          let flag = false
          let len = res.length;
          for(let i = 0; i < len; ++i) {
            if(res[i].username === username) {
              reject('The username was registered!');
              flag = true;
              break;
            }
          }
          if(flag === false) resolve();
        }
      })

    })

  }, function (err) {
    console.log('Maybe the database did not change : ' + err);
  }).then(function () {
        return new Promise((resolve, reject) => {

        const sql = 'insert into users(username, password) values("' + username + '", "' + password + '")'

        connection.query(sql, function (err) {
          if(err) reject(err);
          else resolve('Insert!');
        })

      })
  }, function (err) {
    console.log('Maybe the username exists: ' + err);
  }).then(function (info) {
    if(info) console.log(info);
  }, function (err) {
    console.log('Maybe insert error occurred: ' + err);
  })
}

catch与then混用不太好,一个Promise对应then,但却不是简单地对应一个catch,可以多个then对应一个catch,这个catch只捕捉第一次出现的错误。所以只用then比较好。

另外如果某个Promise未被执行,它的then中的reslove()函数也会被执行,所以这里最后我判断了一下if(info),如果info不是undefined认为其Promise被调用了,认为是执行成功了。

Site by Baole Zhao | Powered by Hexo | theme PreciousJoy