Javascript-форум (https://javascript.ru/forum/)
-   Node.JS (https://javascript.ru/forum/node-js-io-js/)
-   -   как правильно дождаться данных (https://javascript.ru/forum/node-js-io-js/61945-kak-pravilno-dozhdatsya-dannykh.html)

zobretatel 17.03.2016 11:14

как правильно дождаться данных
 
С node.js только столкнулся . Вопрос который задам , наверное относится к избитым ,
но попробовав разные нагугленные варианты проблему решить не удалость.

Суть такова :
1) есть стандартный http сервер , получающий запрос и выдающий ответ
2) есть запрос к ms sql серверу за данными
3) данные успешно извлекаются , но как их передать ПОСЛЕ извлечения не знаю
4) пробовал делать задержку ( цикл for( var i... ){ timeout(); } )
5) ответ на sql запрос получают всегда после окончания работы функции
getMSSQLData , независимо от величины задержки , делал её для эксперимента
достаточно большой .

Вопросы :
1) не понимаю , почему ответ на sql запрос приходит ВСЕГДА после окончания работы
getMSSQLData , независимо от величины задержки , хоть секунда , хоть несколько минут .
Получается , что функция query(...) ставиться в какую-то очередь на выполнение,
а реальное выполнение начинается... КОГДА ?
2) пробовал "подождать" данные внутри getMSSQLData конструкцией типа
while( Line === '' ){} получал зависание

// стандартный http-сервер
...
var Response = httpDat.get(path);
response.writeHead( Response.Error , { 'Content-Type':Response.MIME } );
response.write( Response.Page );
response.end();
...


код был примерно такой :
function getMSSQLData(xServer , xDB , xUser , xPass , xQuery){

     Line = '';

     query(xServer , xDB , xUser , xPass , xQuery);

     for( var i=0 ; i<10 ; i++ ){
           timeout();
     }

     // while( Line === '' ){};

     return( Line );

}



function query(xServer , xDB , xUser , xPass , xQuery){
	sql.connect("...").then(function() {
		new sql.Request().query("SELECT ... FROM ...").then(function(recordset) {
			for( var i=0 ; i<recordset.length ; i++ ){
				Line += recordset[i].DT + '   ::   ' + recordset[i].Val + '\n';
			}
			console.log('result query:'+Line);
			Flag = true;
		});
	});	
}

function timeout(){
       // несколько ненужных вычислений для формирования задержки
}


пробовал async , возможно неправильно , потому, что не помогло

Главный вопрос :
КАК ПРАВИЛЬНО ДОЖДАТЬСЯ ПОЛУЧЕНИЯ ДАННЫХ ОТ MS SQL и ПЕРЕДАТЬ ИХ В КАЧЕСТВЕ ОТВЕТА НА HTTP-запрос ?

andryxx 17.03.2016 14:42

у вас все не по-джедайски.
во-первых, формирование задержек для получения ответов есть зло. тем более таким способом. вы "подвешиваете" сервер на время таймаута. вся прелесть асинхронности node.js теряется.

куда вам следует копать:
во-первых, используйте нормальный, современный способ обмена данными между клиентом и сервером, напрмер на основе вебсокета можно как здесь, либо через socket.io, в конце концов XmlHttprequest.
во-вторых, ответ отправляйте в функции-коллбэке, запускаемой по факту получения ответа от MS SQL

Coriolan161 17.03.2016 20:23

zobretatel,
попробуй запихать задержку в функцию query

MallSerg 17.03.2016 21:38

JS строго однопоточен и никак иначе.
Даже если небо начнет падать на землю return будет вызван раньше чем выполнится любая асинхронная операция (т.е. использование задержки это полное непонимание основ работы JS).

zobretatel 18.03.2016 08:45

andryxx
Цитата:

1) все не по-джедайски ... формирование задержек есть зло
2) используйте нормальный, современный способ обмена данными между клиентом и сервером, напрмер на основе вебсокета можно как здесь, либо через socket.io
1) да , зло . понимаю . в данном случае у меня нет толп клиентов, данные будут забираться достаточно редко, примерно раз в час одним , максимум тремя клиентами (одним из клиентов может быть не браузер, а другой сервер). поэтому подвешивание сервера в данном случае меня не беспокоит.
2) спасибо . раздумываю, попробовать socket или делать выборку из sql заранее , а при запросе возвращать уже готовые данные .

Для интереса напичкал код console.log(..) и вот что получилось :
1) стартует getMSSQLData()
2) стартует query()
3) стартует sql.connect() внутри query()
4) стартует запуск цикла timeout() внутри getMSSQLData()
5) ЗАВЕРШАЕТСЯ getMSSQLData()
6) стартует new sql.Request().query() внутри query()
7) приходит ответ на sql.Request

Coriolan161
Цитата:

задержку в функцию query
попробовал . после sql.connect со всем вложениями . не помогло , почему ) опять не понимаю . ведь запрос к sql уже отослан .

MallSerg
Цитата:

это полное непонимание основ работы JS)
спасибо профессор , с полным непониманием основ JS всё в порядке )

Спасибо друзья
в общем либо , socket попробую , либо кэшировать ответы от sql заранее , так как в принципе понятно , что будет выбрано .
Наверно, из-за соображений времени, сейчас сделаю кэш , но к socket'у обязательно вернусь .

Max Power 18.03.2016 13:36

Комрады, я если честно вообще не понял в чем проблема, но дело пахнет кошмаром и попыткой пристрелить себя в ногу на ровном месте.

Почему нельзя писать простые вещи просто?

var app = module.exports = require('koa')();
var knex = require('koa-knex');
var conf = require('./conf');

app.use(knex(conf.knexConnection));

app.use(function* showUsers() {
  this.body = yield this.knex
    .select('firstname', 'lastname')
    .from('users')
    .where('is_active', true);
});

if (!module.parent) {
  app.listen(conf.app.port, conf.app.host);
  console.log(`listening on http://${conf.app.host}:${conf.app.port}/`);
}

// Выведет JSON:
// [{firstname: 'Маша', lastname: 'Иванова'}, 
// {firstname: 'Вася', lastname: 'Пупкин'}]


PS: А не пахнет ли здесь вообще попыткой вызвать асинхронное синхронно?!!!

zobretatel 18.03.2016 14:29

Max Power
выглядит интересно .

а кстати генераторы не решают проблему асинхронности ?

Яростный Меч 19.03.2016 00:27

насколько я понял, в этом sql используются промисы. Тогда можно так:

function getMSSQLData(xServer , xDB , xUser , xPass , xQuery){
    return sql.connect("...")
        .then(function() {
            return new sql.Request().query("SELECT ... FROM ...");
        })
        .then(function(recordset) {
            var Line = '';
            for( var i=0 ; i<recordset.length ; i++ ){
                Line += recordset[i].DT + '   ::   ' + recordset[i].Val + '\n';
            }
            console.log('result query: ' + Line);
            return Line;
        });
}

// использование
getMSSQLData(...).then(function(Line) {
    // вот здесь работаем с Line
});

Max Power 22.03.2016 05:25

> а кстати генераторы не решают проблему асинхронности

Да, решают. Хотя это в среде теоретиков принято считать хаком (да, собственно, так оно и есть)), на практике это работает неплохо уже сейчас.

Пока все ждут async/await в Ноде, можно красиво писать на генераторах без ада коллбеков и обработки ошибок через 3 строчки уже сейчас.


Часовой пояс GMT +3, время: 00:29.