Эта статья Quickstart по работе с асинхронными операциями в node.js. Эпоха callback'ов прошла, наступила эра генераторов и промисов. Генераторы делают промисы более удобными. А тот факт, что node.js начал поддерживать генераторы и ещё некоторые фичи es6 из коробки, даёт нам возможность применять их на практике в продакшене.
Рассмотрим следующий пример. Структура данных такая: есть пользователи, у пользователя есть маршруты, у маршрутов есть точки. Функция delete репозитиория TripRepository проверяет, что удаляемый маршрут принадлежит указанному пользователю, а потом удаляет все точки этого маршрута и сам маршрут. При этом все запросы к базе асинхронные, а запросы на удаление не блокируют друг-друга, потому мы их можем выполнять одновременно.
var Promise = require('bluebird');
class TripRepository extends Repository {
...
delete(userId, tripId) {
var self = this;
return Promise.coroutine(function*(){
var trip = yield self.findOne({_id: tripId, user: userId});
if (!trip) {
return;
}
yield Promise.all([
self._points.deleteOne({trip: tripId}),
self._trips.deleteOne({_id : tripId})
]);
})();
};
}
Теперь рассмотрим сделаем следующую последовательность действий: поищем в базе маршрут, если его нет, то создадим, а потом удалим его предыдущей функцией TripRepository.delete
var testPromise = Promise.coroutine(function*(){
var trip = yield repo.getById('11');
if (!trip) {
yield repo.add({_id: '11', user: 'musuk'});
}
yield repo.delete('musuk', '11');
})();
testPromise.then(() => {
console.log('coroutine executed');
})
Думаю, что код выглядит достаточно понятно. А теперь вещи, на которые стоит обратить внимание.
- Для работы с промисами и генераторами, я использовал библиотеку bluebird, она дополняет функциональность стандартных es6-промисов.
Promise.coroutine
— это функция bluebird, которая создаёт генератор.var self = this;
я написал поскольку внтури генератора this уже не будет указывать на объект класса TripRepository.Promise.coroutine(function*(){})();
возвращает промис, который можно использовать дальше.
И, в заключении, пример того, как можно сделать запрос к MySQL базе из node.js:
var Promise = require('bluebird');
var co = Promise.coroutine;
var mysql = require('mysql');
Promise.promisifyAll(mysql);
Promise.promisifyAll(require("mysql/lib/Connection").prototype);
Promise.promisifyAll(require("mysql/lib/Pool").prototype);
co(function*(){
var connection = mysql.createConnection({
host : 'localhost',
user : 'root',
password : 'password',
database : 'test'
});
yield connection.connectAsync();
var result = yield connection.queryAsync('select * from test.users');
console.log(result)
connection.end();
})();