Как сделать cинхронный вызов?

Начал пробовать серверный JavaScript, с фреймворком Express и что-то лень мне стало каждый раз роуты прописывать и написал для него обёртку, чтобы все вызовы с app.get и app.post шли в psycho.router, а он дальше сам проверяет есть ли такой модуль и есть ли у него такой метод. Если есть, то вызывается метод который возвращает данные, а дальше сразу подцепляется шаблон куда эти данные выводятся.

var psycho = {
	syncConfig: function() {	},
	language: function(language) { return config.languages.indexOf(language) != -1;},
	method: function(module,method) {return typeof module[method] === "function";},
	loadModule: function(module) {
		try {
			return require('./modules/' + module + '.js');
		} catch(err) {
			return false;
		}
	},
	render: function(controller,template,layout,vars) {
		var content = swig.renderFile('views/' + (controller[0].toUpperCase() + controller.slice(1)) + '/' + template + '.html',vars);
		return swig.renderFile('views/Layout/' + layout + '.html',merge({content:content},vars));
	},
	_404_: function(vars) {
		return this.render('Elements','404','elements',
			merge(
				vars,
				{
					title: __('404 Страница не найдена') + config.other.head.titlePostfixFull,
					keywords: __('404, страница не найдена'),
					description: __('Страница не найдена')
				}
				
			)
		);
	},
	router: function(type,req,res) {
		if (config.checkip && config.allowip.indexOf(req.connection.remoteAddress) == -1) {
	        res.status(200).send("look at my horse my horse is amazing");
	    } else {   	
	    	var url = req.url.split('/');
	    	var url = url.slice(1,url.length + 1);
	    	
	    	if(req.url == '/') {
		    	res.status(200).send(this.render(config.defaultRoute[0],config.defaultRoute[1],config.defaultLayout,
		    		merge(this.loadModule(config.defaultRoute[0])[config.defaultRoute[1]](req,res),{
		    				lang: ['/' + config.defaultLanguage, config.defaultLanguage],
		    				robots: config.other.head.robots,
			    		}
		    		)
		    	));
	    	} else if(this.language(url[0])) {
	    		if (url[1] == undefined) {
		    		res.status(200).send(this.render(config.defaultRoute[0],config.defaultRoute[1],config.defaultLayout,
							merge(this.loadModule(config.defaultRoute[0])[config.defaultRoute[1]](req,res),{
								lang: ['/' + url[0], url[0]],
								robots: config.other.head.robots
							}
						)
					));
	    		} else {
		    		var module = this.loadModule(url[1]);
	    			if (!module) {
	    				res.status(404).send(this._404_({lang: ['/' + url[0],url[0]]}));
	    			} else {
	    				if (url[2] == undefined) {
			    			if (this.method(module,'main')) {
			    				res.status(404).send(this._404_({lang: ['/' + url[0],url[0]]}));
			    			}
		    			} else {
		    				if (this.method(module,url[2])) {
		    					res.status(200).send(this.render(url[1],url[2],config.defaultLayout,merge(module[url[2]](req,res),{
											lang: ['/' + url[0], url[0]],
											robots: config.other.head.robots,
										}
									)
								));	    					
		    				} else {
		    					res.status(404).send(this._404_({lang: ['/' + url[0],url[0]]}));
		    				}
		    			}
	    			}
	     		}
	    	} else {
				res.status(404).send(this._404_({
	    			lang: ['/' + config.defaultLanguage,config.defaultLanguage]
				}));  	
	   	 	}
	    }
	    res.end();
	}
    };
    
    app.get('*', function(req, res) { 
		psycho.router('get', req, res);
	});
	app.post('*', function(req,res) {
		psycho.router('post', req, res);
	});


var LanguageWord = sequelize.define('LanguageWord', {
	id: {
		type: Sequelize.INTEGER,
		autoIncrement: true,
		primaryKey: true
	},
	phrase: {
        type: Sequelize.STRING(256),
        allowNull: false,
        unique: true,
    }
});

global.modelLink = function() { // просто так
	return LanguageWord;
};


ещё надоело писать запросы руками и решил использовать ORM - Sequelize.js
так вот о нём и речь.
обращаюсь к /ru/admin/users
соответственно подтягивается admin.js и выполняется метод user
module.exports = {
	users: function(req,res) {
		var LanguageWord = modelLink();
			
		console.log("\n\n\n\n\n");
		console.log("START QUERY");
		console.log(LanguageWord.findAll().then(function(word) {
			
			var results = [];
			for(var i = 0; i < word.length; i++) {
				results.push(word[i].dataValues);
			}
			return results;
			console.log("THEN QUERY");
		}));
		console.log("END QUERY");
		console.log("\n\n\n\n\n");
		return  {
			title:	__('Пользователи') + res.locals.head.titleDelimiterSpaces + __('Админ-панель') + res.locals.head.titlePostfixFull,
		};
	},
};


но return срабатывает раньше чем приходит ответ от базы. да оно в принципе и логично.
дайте пожалуйста элегантный пример как дождаться выполнения одного запроса и нескольких, а из него передать данные в этот возвращаемый объект который содержит title

да, я знаю про node-sync, прочитал десяток тем, но до сих пор не понимаю как дождаться ответа.

если бы я не писал этой обёртки, которую привел выше, то можно было бы всё организовать с помощью каллбэков, но что есть то есть.
  • Вопрос задан
  • 2775 просмотров
Решения вопроса 1
Staltec
@Staltec
Node.js разработчик
дайте пожалуйста элегантный пример как дождаться выполнения одного запроса и нескольких, а из него передать данные

async.js (https://github.com/caolan/async) - облегчает работу с колбеками. Но у него фатальный недостаток, он для асинхронной работы. Этот модуль представляет шикарные возможности обработки последовательных задач (методы вида *Series, waterfall), но `последовательное` не значит `синхронное`.

В целом по вашему вопросу. Express работает с запросами как с потоками. Нельзя работать в Node с потоком синхронно. Синхронным кодом вы тупо блокируете цикл событий.

Вы сами себе придумали велосипед с квадратными колёсами и теперь спрашиваете как сделать так чтобы на нём можно было ездить.

Где место синхронному коду в Node.js приложении работающему с потоками ввода/вывода? Ответ: в области инициализации.
Ответ написан
Пригласить эксперта
Ваш ответ на вопрос

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

Похожие вопросы