V
V
Valentine2016-07-12 11:06:38
MySQL
Valentine, 2016-07-12 11:06:38

Promises and database connection, how to work with them correctly?

I have a user object (Member), whose methods work with the database (mysql).
The class itself:

'use strict'

var connection  = require('./mysqlconnection');

class Member {
  constructor(user) {
    console.log('create member...');
    this.db 	= connection();
    this.user 	= user;
    this.params	= [];
  }

  loadMember() {
    console.log('try to load member...');
    let promise = new Promise((resolve, reject) => {
      var db = connection();
      db.query('SELECT * FROM `pfp_bot_user` WHERE `uid` = '+this.user.id, function(error, rows){
        if (error)
          reject(new Error(error));

        console.log('member loaded...');
        if (!rows.length)
          reject(new Error('Member not found!'));
        resolve(rows);
      });
    });
    return promise;
  } 

  saveMember(user) {
    let promise = new Promise((resolve, reject) => {
      var row = {
        uid : user.id, firstname : user.first_name, lastname : user.last_name, username : user.username
      };
      var db = connection();
      db.query('INSERT INTO `pfp_bot_user` SET ? ', row,  function(error, result){
        console.log(result);
        if (error)
          reject(error);

        resolve(result);
      });
    });
    return promise;
  }

  getParam(name) {
    if (this.params[name] !== undefined)
      return this.params[name];
    return null;
  }

  saveParam(name, value) {
    let promise = new Promise((resolve, reject) => {
      var row = {
        uid : this.user.id, name : name, value : value
      };
      var db = connection();
      db.query('INSERT INTO `pfp_bot_user_values` SET ? ', row,  function(error, result){
        console.log(result);
        if (error)
          reject(new Error(error));

        resolve(result);
      });
    });
    return promise;
  }

  loadParams() {
    // ...
  }
}

module.exports = Member;

There are 2 problems:
Problem 1.:
When a request comes in, I create it and call the loadMember function, which returns a promise.
But I, let's say in the loadMember function, need to asynchronously execute several requests.
but if I put subsequent requests in a callback, then I lose this of my class, it’s clear that I need to put it in a closure, but this is some kind of PPC if there is a long cascade of nested requests with their callbacks.
Better yet, they (queries to the database) are executed when created in the constructor! But an external program wants to work with an already loaded object, and does not want to wait for the completion of loading user data, how is this implemented so that there are no locks?
Problem 2.:
As you can see, the object takes the connection from some connection() function.
Here is its code:
'use strict'

var mysql       = require('mysql');

var db = null;

function getConnection() {

  if (!db || db.state !== 'connected') {
        db = mysql.createConnection({
                          // ...
        });
  }
  db.connect();
    return db;
}
module.exports = getConnection;

It is planned that this is some global function for creating connections.
It is clear that this is some kind of slag, since the connection may be busy for other requests.
It is possible to organize a connection pool, but they need to be closed, and with all these promises, I still haven’t really figured out where to close it, and in fact, in the process of executing the program, I need to somehow pass it through promises, so that when I decide to close it, there is something to close.
What to do with it? How is it decided?
I really hope for useful information! ))

Answer the question

In order to leave comments, you need to log in

1 answer(s)
D
Dmitry Belyaev, 2016-07-12
@Tpona

In order not to lose this - use arrow functions, unlike ordinary ones, they use this and arguments from the closure.
If you need to execute several queries in sequence, use a chain of promises:

loadMember() {
  return new Promise((resolve, reject) => {
    db.query('sql...', (err, result) => {
      if(err) {
        return reject(err);
      }
      resolve(result);
    }
  }).then(result1 => {
    return new Promise((resolve, reject) => {
      //..
    });
  });
}

And also, if you reject a promise, end the handler function with return
If you need to execute several promises in parallel, use
Promise.all([promise1, promise2 /*, ... */]).then(results => {});

Didn't find what you were looking for?

Ask your question

Ask a Question

731 491 924 answers to any question