2013-07-26 3 views
1

Я пишу webapp, используя express.js.Node.js прослушивает изменение переменной сеанса и запускает событие, отправленное сервером

Мой WebApp достигает следующих

  1. сообщения пользователя 100 JSON Объекты
  2. Каждый объект JSON, обрабатывается с помощью службы вызова
  3. После того, как вызов службы завершается, переменная сеанса увеличивается
  4. При добавлении переменной сеанса серверное событие должно быть отправлено клиенту для обновления индикатора выполнения.

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

Прослушивание переменного изменения - не единственное решение, которое я ищу?

Мне нужно добиться отправки события, отправленного сервером, после обработки объекта JSON.

Любое соответствующее предложение приветствуется

Edit (основано на комментарий Альберто Zaccagni в)

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

function processRecords(cmRecords,requestObject,responseObject) 
{ 
    for (var index = 0; index < cmRecords.length; index++) 
    { 
     post_options.body = cmRecords[index]; 
     request.post(post_options,function(err,res,body) 
     { 
      if(requestObject.session.processedcount) 
       requestObject.session.processedcount = requestObject.session.processedcount + 1; 
      else 
       requestObject.session.processedcount = 1; 

      if(err) 
      { 
       appLog.error('Error Occured %j',err); 
      } 
      else 
      { 
       appLog.debug('CMResponse: %j',body); 
      } 

      var percentage = (requestObject.session.processedcount/requestObject.session.totalCount) * 100; 

      responseObject.set('Content-Type','text/event-stream'); 
      responseObject.json({'event':'progress','data':percentage}); 
     }); 
    }; 


} 
  1. Когда первая запись обновляется и сервер боковое событие запускается с использованием объекта responseObject (объект экспресс-ответа)

  2. Когда вторая запись обновляется, и я пытаюсь запустить событие на стороне сервера, используя тот же объект responseObject. Я получаю сообщение об ошибке сказав не может установить заголовок ответа, который уже был послан

+0

Почему вы должны слушать на переменную? Почему вы не отправляете событие сразу после его обновления? –

ответ

0

Трудно точно знать, что ситуация не видя маршруты/действия, которые вы имеете в своем главном приложении ...

Однако я считаю, что проблема, с которой вы сталкиваетесь, заключается в том, что вы пытаетесь отправить два набора заголовков клиенту (браузеру), что запрещено. Причина, по которой это недопустимо, заключается в том, что браузер не позволяет вам изменять тип содержимого ответа после отправки начального ответа ... поскольку он использует это как показатель того, как обрабатывать ответ, который вы его отправляете. Вы не можете изменить ни один из этих (или любых других заголовков) после того, как вы отправили их клиенту один раз (один запрос -> один ответ -> один набор заголовков обратно клиенту). Это предотвращает появление вашего шизофреника (переключаясь с ответа «200 Ok» на «400 Bad Request», например).

В этом случае по первому запросу вы сообщаете клиенту: «Привет, это был действительный запрос, и вот мой ответ (через статус 200, который либо установлен в другом месте, либо предполагается ExpressJS), и держите канал связи открытым, чтобы я мог отправлять вам обновления (путем установки вашего типа контента на text/event-stream) ».

Что касается «исправления» этого, есть много вариантов. Когда я это сделал, я использовал функцию pub/sub redis, чтобы действовать как «труба», которая соединяет все.Таким образом, поток был так:

  1. Некоторые клиент посылает запрос на /your-event-stream-url

    В этом запросе настройки Redis абонента. Все, что входит в эту подписку, может быть обработано, как вы хотите. В вашем случае вы хотите «отправить некоторые данные по трубе клиенту в объекте JSON с атрибутом по крайней мере data». После того, как вы настроили этот клиент, вы просто возвращаете ответ «200 Ok» и задаете тип содержимого «text/event-stream». Редис позаботится обо всем остальном.

  2. Затем еще один запрос к другому URL конечной точки выполняющую задачу «размещения объекта JSON», нажав /your-endpoint-that-processes-json. (Примечание: Очевидно, это требование может быть одним и тем же пользователем/браузер ... но приложение не знает/заботится об этом)

    В этом действии вы обрабатываете данные своих JSON, увеличиваете свои счетчики или выполняете все ... и возвращаете ответ 200. Тем не менее, одна из вещей, которые вы делаете в этом действии, - «опубликовать» сообщение на канале Redis, которое ваши подписчики с первого шага слушают, чтобы клиенты получали обновления. Технически это действие не нужно возвращать ничего клиенту, предполагая, что у пользователя будет какая-то обратная связь на основе кода состояния 200 или на отправленном сервером событии, которое отправляется по трубопроводу ...

Ощутимый пример, который я могу вам дать, это this gist, который является частью this article. Обратите внимание, что этой статье пару лет, поэтому некоторые из кода, возможно, придется немного подкорректировать. Также обратите внимание, что это не гарантируется как нечто большее, чем пример (т. Е. Он не был «проверен на нагрузку» или что-то в этом роде). Однако это может помочь вам приступить к работе.

0

Я придумал решение, пожалуйста, дайте мне знать, правильно ли это сделать?

Будет ли это решение работать через сеансы?

стороне сервера Код

var events = require('events'); 
var progressEmitter = new events.EventEmitter(); 

exports.cleanseMatch = function(req, res) 
{ 
    console.log('cleanseMatch Inovked'); 
    var progressTrigger = new events.EventEmitter; 
    var id = ''; 
    var i = 1; 

    id = setInterval(function(){ 
     req.session.percentage = (i/10)*100; 
     i++; 
     console.log('PCT is: ' + req.session.percentage); 
     progressEmitter.emit('progress',req.session.percentage) 

     if(i == 11) { 
     req.session.percentage = 100; 
     clearInterval(id);    
     res.json({'data':'test'}); 
     } 
    },1000); 
} 

exports.progress = function(req,res) 
{ 
    console.log('progress Inovked'); 
    // console.log('PCT is: ' + req.session.percentage); 

    res.writeHead(200, {'Content-Type': 'text/event-stream'}); 
    progressEmitter.on('progress',function(percentage){ 
     console.log('progress event fired for : ' + percentage); 
     res.write("event: progress\n"); 
     res.write("data: "+percentage+"\n\n"); 
    }); 
} 

стороне клиента Код

var source = new EventSource('progress'); 
source.addEventListener('progress', function(e) { 
    var percentage = JSON.parse(e.data); 
    //update progress bar in client 
    App.updateProgressBar(percentage); 
}, false); 
Смежные вопросы