2016-09-26 2 views
1

Я новичок в узле и застрял в обработке нескольких задач async.Узел js - как обрабатывать несколько асинхронных задач

За исключением узла, у меня есть еще один сервер (S1), который немедленно не возвращает данные на запросы, он может возвращать несколько типов данных, а также может отправлять уведомления, не запрашивая их конкретно, поэтому узел должен прослушивать данные из него, проанализировать его и действовать соответствующим образом.

Подключение к этому серверу (S1) осуществляется с помощью:

S1 = net.createConnection({'host':S1Host, 'port': S1Port}); 

И узел прослушивает данных с:

S1.on('data', function(data){ 
    S1DataParse(data); 
}); 

Я должен направлять правильные данные (после разбора его) к конкретному запросу POST.

Я попытался использовать для этого асинхронный модуль, но безуспешно. То, что я пытаюсь сделать:

var asyncTasks = []; 

app.post('/GetFooFromS1', function(req, res){ 

    asyncTasks.push(function(callback){ 
    // Send request to S1 
    S1.write({'type':'foo'}); 
    }); 

    async.parallel(asyncTasks, function(response){ 
    res.setHeader('Content-Type', 'application/json'); 
    res.json({'status':'success', 'value':response}); 
    }); 
}); 

и еще одна задача в S1DataParse:

function S1DataParse(){ 
    if(data.type='foo'){ 
    asyncTasks.push(function(callback){ 
     callback(data); 
    }); 
    } 
} 

Но, конечно, вторая задача не добавляется в массив asyncTasks. Я действительно застрял в этом. Не могли бы вы мне помочь?

Благодаря

- = - = - = - Edit - = - = - = -

В конце концов, я наткнулся с событий и EventEmitter().

Из запроса POST я вызываю функцию, отправляющую запросы на сервер данных (DataServerClientGet). В этой функции я регистрирую слушателя, который получит будущие данные. eventEmitter.on ('getData', returnDataServerData);

Все работает отлично, за исключением одной вещи. Когда я обновляю страницу или добавляю другие запросы POST, я получаю сообщение об ошибке:

Ошибка: не удается установить заголовки после их отправки.

Было бы здорово решить эту проблему. Помоги мне, пожалуйста.

Спасибо;)

Весь код выглядит следующим образом:

var express = require('express'); 
var app = express(); 
var http = require('http').Server(app); 
var bodyParser = require('body-parser') 
var net = require('net'); 
var events = require('events'); 

var dataServerHost = '127.0.0.1'; 
var dataServerPort = 12345; 
var dataServerClient; 
var logMsg; 

var eventEmitter = new events.EventEmitter(); 


/*******************************************/ 
//    Init 
/*******************************************/ 
app.use(bodyParser.json()); 
app.use(bodyParser.urlencoded({extended: true})); 
app.use(express.static(__dirname + '/public')); 


/*******************************************/ 
//  Connect to the data server 
/*******************************************/ 
DataServerConnect(); 


/*******************************************/ 
// Open listener on port 3000 (to browser) 
/*******************************************/ 
http.listen(3000, function(){ 
    logMsg = 'listening on *:3000'; 
    console.log(logMsg); 
}); 


/*******************************************/ 
//    Routing 
/*******************************************/ 
app.get('/', function(req, res){ 
    res.sendFile(__dirname + '/index.html'); 
}); 

app.post('/GetDataFoo', function(req, res){ 
    var msg; 
    var size; 

    msg ='\n{"Type":"Query", "SubType":"GetDataFoo","SearchFilter":""}'; 
    size = msg.length; 

    logMsg = 'Client to DataServer: GetDataFoo'; 
    console.log(logMsg); 

    DataServerClientGet('GetDataFoo', size, msg, res); 
}); 


/*******************************************/ 
//    Functions 
/*******************************************/ 
function DataServerConnect(){ 
    dataServerClient = net.createConnection({'host':dataServerHost, 'port': dataServerPort}, function(){ 
    logMsg = 'Connected to DataServer ['+dataServerHost+':'+dataServerPort+']'; 
    console.log(logMsg); 
    }); 

    dataServerClient.on('data', function(data){ 

    logMsg = 'DataServerData>>>\n'+data.toString()+'DataServerData<<<'; 
    console.log(logMsg); 

    DataServerDataParse(data.toString()); 
    }); 

    dataServerClient.on('end', function(){ 
    logMsg = 'Disconnected from DataServer'; 
    console.log(logMsg); 
    }); 
} 

function DataServerClientGet(type, size, msg, res){ 
    dataServerClient.write('Type: Json\nSize: '+size+'\n\n'+msg, function(err){ 

    var returnDataServerData = function returnDataServerData(results){ 
    res.setHeader('Content-Type', 'application/json'); 
    res.json({'status':'success', 'value':results}); 
    } 
    eventEmitter.on('getData', returnDataServerData); 
} 

function DataServerDataParse(json){ 
    if(json.Type=='GetDataFoo') 
    { 
    var MessageList = json.MessageList; 
    eventEmitter.emit('getData', MessageList); 
    } 
} 

- = - = - = - Edit - = - = - = -

Ошибка: Невозможно установить заголовки после их отправки., вызванный добавлением одного и того же прослушивателя одного и того же типа каждый раз, когда вызывался DataServerClientGet, и res отправлял несколько раз.

Я решил это, добавив: removeListener (событие, слушатель) сразу после res, внутри функции. Во всяком случае, я думаю, что это неправильно и может вызвать проблемы, если будет несколько призванием DataServerClientGet с тем же типом и т.д.

ответ

0

Существует необязательный параметр обратного вызова, который можно передать, чтобы написать функцию (docs), что-то вроде:

S1.write({'type':'foo'},function(err){ 
    if(err){ 
    //Handle error 
    }else{ 
    res.setHeader('Content-Type', 'application/json'); 
    res.json({'status':'success', 'value':response}); 
    } 
}) 

Это может работать с почтовым маршрутом, но в вашем слушателе «данных», вы не можете передавать данные от сервера к клиенту, когда не соединение инициализируется клиентом (это не bidireccional), если вы хотите bidireccional поведения, может проверить socket.io

+0

Привет, Большое спасибо, обратный вызов в записи был очень полезным. Все еще я должен позаботиться о возвращенных данных, поступающих на S1.on ('data'). Как я уже говорил, это асинхронно, и я должен приложить результат к правильному запросу POST. Также мне нужно получить ссылку на res где-нибудь позже на код, а не на сам запрос POST. –

+0

, как я уже сказал, не думаю, что это возможно, потому что после ответа HTTP return нет связи. – cshion

+0

Проверьте последний отредактированный текст и код, которые я опубликовал. Мне удалось отправить запрос POST, пока эмиттер не получит соответствующие данные с другого сервера и только затем вернет res. Осталось только обработать ошибку: Ошибка: не удается установить заголовки после их отправки. У меня также появилось ощущение, что способ передачи пропусков через код неверен. Возможно, ошибка связана с этим неправильным обращением. –