Tpona
@Tpona
Ужасный перфекционист

Промисы и подключение к БД, как правильно работать с ними?

Есть у меня некий объект пользователь (Member), методы которого работают с БД (mysql).

Сам класс:
'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;


Есть 2 проблемы:

Проблема 1.:
Когда приходит запрос, я создаю его и вызываю функцию loadMember, которая возвращает промис.
Но мне, допустим в функции loadMember нужно асинхронно выполнить несколько запросов.
но если я буду последующие запросы вкладывать в коллбек, то у меня теряется this моего класса, ясно что нужно класть его в замыкание, но это ппц какой то, если будет длинный каскад из вложенных запросов с их коллбеками.

А еще лучше, чтобы они (запросы к бд) выполнялись при создании в конструкторе! Но внешняя программа хочет работать уже с прогруженным объектом, и ждать завершения загрузки данных пользователя ей не хочется, как это реализуется, чтобы не было блокировок?

Проблема 2.:
Как видно, объект берет подключение из некоторой функции connection()
Вот ее код:
'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;

Планируется, что это некоторая глобальная функция по созданию подключений.

Ясно что это какой то шлак, так как подключение может быть занято для выполнения других запросов.
Есть возможность организовать пулл подключений, но их надо закрывать, а со всеми этими промисами я пока не придумал толком где его закрывать да и собственно в процессе выполнения программы через промисы надо его как-то прокидывать, чтобы когда я решу его закрыть было что закрывать.
Что делать с этим? Как решается?
Очень надеюсь на полезную информацию! ))
  • Вопрос задан
  • 851 просмотр
Решения вопроса 1
bingo347
@bingo347 Куратор тега JavaScript
Crazy on performance...
Чтоб не терять this - используйте стрелочные функции, в отличии от обычных они используют this и arguments из замыкания
Если нужно выполнить несколько запросов последовательно, используйте цепочку промисов:
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) => {
      //..
    });
  });
}

Ну и еще, если режектите промис - завершайте функцию обработчик через return
Если нужно выполнить несколько промисов параллельно - используйте
Promise.all([promise1, promise2 /*, ... */]).then(results => {});
Ответ написан
Пригласить эксперта
Ваш ответ на вопрос

Войдите, чтобы написать ответ

Войти через центр авторизации
Похожие вопросы