Warning: file_get_contents(/data/phpspider/zhask/data//catemap/9/javascript/393.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
Javascript 了解如何将Redis与Node.js和服务器发送的事件一起使用_Javascript_Node.js_Heroku_Redis_Server Sent Events - Fatal编程技术网

Javascript 了解如何将Redis与Node.js和服务器发送的事件一起使用

Javascript 了解如何将Redis与Node.js和服务器发送的事件一起使用,javascript,node.js,heroku,redis,server-sent-events,Javascript,Node.js,Heroku,Redis,Server Sent Events,我的项目使用Nodejs作为代理服务器构建,以与外部API通信 API通过Redis(发布/订阅)发送产品更新;代理服务器处理消息并通过SSE(服务器发送事件)将其发送到客户端 这是我第一次使用Redis和SSE,在线查找教程似乎很容易实现,我做到了 在客户端,我刚刚创建了一个EventSource,一旦收到更新,我就会对它做一些事情: // Client Side var source = new EventSource('/redis'); // /redis is path to prox

我的项目使用Nodejs作为代理服务器构建,以与外部API通信

API通过Redis(发布/订阅)发送产品更新;代理服务器处理消息并通过SSE(服务器发送事件)将其发送到客户端

这是我第一次使用Redis和SSE,在线查找教程似乎很容易实现,我做到了

在客户端,我刚刚创建了一个
EventSource
,一旦收到更新,我就会对它做一些事情:

// Client Side
var source = new EventSource('/redis'); // /redis is path to proxy server
source.addEventListener('items', handleItemsCallback, false);
source.addEventListener('users', handleUsersCallback, false);
source.addEventListener('customers', handleCustomersCallback, false);

// Function sample...
function handleItemsCallback (msg) {
   // Do something with msg...
}
在代理服务器中,我创建了一个控制器,路由到
/redis
,以处理redis消息:

exports.redisUpdates = function (req, res) {
    // Redis Authentication
    var redisURL = url.parse(process.env.REDISCLOUD_URL);
    var client = redis.createClient(redisURL.port, redisURL.hostname, {ignore_subscribe_messages: false});
    client.auth(redisURL.auth.split(":")[1]);

    // let request last as long as possible
    req.socket.setTimeout(0);

    // Subscribe to channels
    client.subscribe('items', 'users', 'customers');

    // Handle messages
    client.on('message', function (channel, message) {
        res.write('retry: 5000\n');
        res.write('event: ' + channel + '\n');
        res.write('data: ' + message + '\n\n');
        res.flush(); // If I do not add this it doesn't push updates to the client (?)
    });

    //send headers for event-stream connection
    res.writeHead(200, {
      'Content-Type': 'text/event-stream',
      'Cache-Control': 'no-cache',
      'Connection': 'keep-alive'
    });
    res.write('\n');

};
在开发环境中本地使用它可以正常工作,但在生产中使用它会产生几个不同的错误,该应用程序托管在Heroku上,Heroku Metrics显示了几个H18H12H27错误

有时
/redis
调用返回状态
503


我想了解的是,如果我正确地使用了这些服务,为什么所有教程都没有提到
res.flush()
,而且我自己发现了让它第一次工作的方法…

公平地说,这个问题没有真正的答案,有几个原因。我不知道你在谈论哪些教程,因为你在问题中没有引用任何教程。我不能代表那些编写未引用教程的人发言。它们可能是错误的,或者您试图实现的体系结构在某种程度上有所不同。我也不知道您在项目中使用的是什么框架或可选中间件

现在,说了这么多,我有几件事可以和大家分享,也许能帮上忙

您发现的大多数教程可能不会无限期地打开连接并读取流。当进程结束时,http响应将以.end()或类似的方式关闭。因为HTTP响应是一个写流,所以它遵循与任何其他流相同的规则。您可以在这里找到许多关于流的好信息:

需要了解的重要一点是,流可以有一个缓冲区,而大多数http框架都支持压缩,从而使用缓冲区。下一个链接中的代码示例是一个很好的例子,说明了框架在幕后会为您做些什么(当然是一个最小的实现)

由于希望继续更新输出,因此必须等到达到输出缓冲区大小,或者必须调用.flush()

如果您使用的是express,请查看与压缩中间件相关的下一篇堆栈溢出文章。我相信您必须为您的
/redis
路线禁用它

我希望这有点帮助。就像我说的,这个问题很难回答