[Асинхроность и nodejs] Кто что использует против callback hell и почему?

Добрый день всем.

Связавшись с nodejs и выбрав его как основу новому проекту, я столкнулся с чем-то новым и поначалу очень не понятным для меня, это была асинхроность. Весь мой код был похож на пирамидки из колбеков стремящихся к правому краю экрана. Со временим открыл для себя пару вариантов async и Q. Пытался подружиться с fibrous-ом, но увы. Что-то слышал про yields и генераторы, но тоже не срослось. Хотел бы услышать ваше мнение по этому вопросу и узнать есть ли понацея?

Спасибо, продуктивного дня.
  • Вопрос задан
  • 6363 просмотра
Решения вопроса 1

Это популярная проблема, все пытаются с ней бороться, придумывают разные инструменты, библиотеки и прочее. Но скажу, что при хорошей архитектуре вложенность функций редко переваливает за 2 штуки - а это уже никакой не `хэл`. Ну вот посмотрите на метод в котором у вас этот самый `хэл`. Это же явное нарушение SOLID - один метод обрабатывает данные, куда-то их посылает, ждет в коллбэке ответ, с ним что-то делает, потом снова вызывает другую асинхронную функцию и опять ждет ответ, и так несколько раз. Поэтому `коллбэк хэл` - это классная штука, которая помогает разбивать код на независимые функции - принял данные, что-то сними сделал, отправил дальше как эти данные, так и другие аргументы. Точка.

Ответ написан
Комментировать
Пригласить эксперта
Ответы на вопрос 3
MarcusAurelius
@MarcusAurelius
автор Impress Application Server для Node.js

Выше очень правильно заметили, что нужно разбивать методы на логические части поменьше, а не писать простыней, но еще есть проблема в том, что нужно сделать несколько запросов в БД или другим внешним источникам, к файлам, другим серверам, и потом на основе всех фрагментов данных, полученных асинхронно, исполнить бизнес-логику и сформировать ответ. Асинк прекрасно с этим справляется, как в примере ниже.


var dataRequests = [];
// массив запросов к разным данным (БД, файлы, сетевые вызовы)
var dataResults  = {};
// я предпочитаю не использовать массив results, который дает async
// а вместо этого делать именованные фрагменты данных
// и писать их в свой хеш

// добавляем один запрос к данным
dataRequests.push(function(callback) {
	db.queryRow(
		'SELECT * FROM TableName1 where Field1=?', [someValue1],
		function(err, res) {
			dataResults.firstPiceName = res;
			callback(err, null);
		}
	);
});

// добавляем второй запрос к данным
dataRequests.push(function(callback) {
	db.queryValue(
		'SELECT count(*) FROM TableName2 where Field2=?',
		[someValue2],
		function(err, res) {
			dataResults.secondPiceName = res;
			callback(err, null);
		}
	);
});

// вызываем массив запросов асинхронно
async.series(dataRequests, function(err, results) {
	// тут делаем бизнес-логику над dataResults в котором у нас есть
	// все фрагменты данных .firstPiceName и .secondPiceName
	// и формируем общий результат
});

А еще рекомендую ставить тег "node.js" на вопросы по ноде.

Ответ написан

Ну основные подходы вы перечислили.

За yield, генераторами и обертками над ними - будующее, но пока они доступны только в нестабильной ветке 0.11. Fibers - попытка их эмулировать, мне не очень нравится, да и смысл, если скоро генераторы появятся в стабильной ветке? Q и прочие промисы - хорошая штука, но в js по старой привычке использую async.

Текущие проекты пишу на LiveScript, в нем с последовательными асинхронными операциями помогает такая штука, как backcall'ы, пример.

Ответ написан
Комментировать
@zohkiller

Есть IcedCoffeeScript http://maxtaco.github.io/coffee-script/ почти (а это и есть) как кофе скрипт, только не вызывает рвотных позывов как LiveScript

Ответ написан
Ваш ответ на вопрос

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

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