外部程序返回后Nodejs如何更新客户端?
Nodejs how to update client after external program has returned?
我正在编写一个主要做两件事的 NodeJS 应用程序:
- 运行 网络 GUI(简单 HTML/JS)
- 运行 基于用户输入的外部程序(二进制文件)
我希望能够异步地 运行 这些外部程序,因为它们可能需要几分钟才能完成。当他们 return 时,我想更新 Web GUI 以显示结果。这是最基本的概念:
- 用户输入参数并按下操作按钮。
- 服务器运行是带有用户参数的外部程序。
- 当程序 returns 时,服务器获取输出(XML 文件)并放入
数据库中的内容。
- 服务器随后使用来自数据库的结果更新客户端。
需要注意的是,用户可以同时运行多个外部程序,参数不同。
当外部程序完成时,我应该如何更新客户端(Web GUI):是否必须由客户端轮询更新(例如,通过查看数据库是否结果在这里)?或者有没有办法 "push" 从服务器到客户端?
我也在查看设计示例以实现此目的,因此请随时提供有关此体系结构的建议和资源。
我开始在我的应用程序中使用队列,我和你有同样的问题。
我认为(但仍未尝试)的一个解决方案是在用户启动此类异步进程时启动套接字(使用 socket.io)并发送回调 url(指向您的快递服务器)到流程。
回调将有一个 client/session id 参数来标识发出请求的人并选择正确的套接字将消息推回。
使用套接字,您不必从客户端到服务器进行池化。
我觉得这叫Pub/Sub。 Redis 等一些技术也可以帮助实现它。
我也想收到有关此方法的反馈。你怎么看?
好的,看来您需要两种类型的更新。
1) 当外部程序执行完毕
...你需要告诉快递服务器发生了什么以及结果。这里最简单的方法是简单地在 express 的 public(或私有)API 上点击一个方法,它已经有了。
例如,使用 request library:
var request = require('request');
var EXPRESS_URL = 'http://localhost:8080/api/task'
//...
// This is called after you save results to database
function onTaskCompleted(taskId, result) {
request.put(
{
url: EXPRESS_URL + '/' + taskId,
json: result
},
function (err, httpResponse, body) {
// Handle response
}
);
}
如果这些服务器不在同一台机器上,您还需要在您的 express 服务器中有相应的 /api/task/:id/
路由和一些安全措施。
2) 当 express server 发现一个任务已经完成时
...您需要通知当前活跃的用户。在这种情况下,这将发生在 /api/task/:id/
请求处理程序中。从这里通知用户浏览器的最佳方式是通过 socket.io。在 node 中安装真的很容易,并且会解决所有遗留浏览器问题。
在服务器上,你可以这样使用它:
app.put('/api/task/:id', function (req, res) {
var payload = {
id: req.params.id,
result: req.data
};
io.emit('task_completed', payload);
});
在客户端:
io.on('task_completed', function (data) {
alert('Task ' + data.id + ' has finished with result ' + data.result);
});
您肯定想使用 Socket.io,正如 Tulio 所建议的。您特别询问了如何更新客户端的想法,所以我假设您知道如何知道服务器何时执行完外部程序。
websocket 允许您的服务器随时将数据发送回客户端,例如当您的程序完成时。它消除了您使用长轮询或 ajax 技术的需要,这些技术可能会比您希望的占用更多的开发周期。
Socket.io 是 最好、最受欢迎的 websocket 包装器之一。它是跨浏览器的,甚至移动支持也是无与伦比的。基本上,如果你是 运行 一个 node.js 服务器,你想使用 socket.io。
这是我昨晚推荐给一位同事的很棒的教程:
https://nodesource.com/blog/understanding-socketio
而且,为了节省您大量的搜索时间,我想我还要提到创建跨文件客户端套接字。您只需在主 html 文件中声明套接字变量:
index.html:
<html>
<script src="https://cdn.socket.io/socket.io-1.3.4.js"></script>
<script>
var socket;
var connected=false;
</script>
</html>
main.js:
socket = io.connect('http//localhost'); //Make sure you include http//
socket.on('connect'){
connected = true;
});
secondary.js:
setInterval(function(){
if(connected === true){
socket.emit('doesThisWork', true);
};
}, 100);
此外,要强制建立新连接,您可以:
socket = io.connect('http//localhost', {'force new connection': true);
为了确保套接字安全,您需要保护您的 url... 例如HTTPS 也能确保您的套接字安全。
我正在编写一个主要做两件事的 NodeJS 应用程序:
- 运行 网络 GUI(简单 HTML/JS)
- 运行 基于用户输入的外部程序(二进制文件)
我希望能够异步地 运行 这些外部程序,因为它们可能需要几分钟才能完成。当他们 return 时,我想更新 Web GUI 以显示结果。这是最基本的概念:
- 用户输入参数并按下操作按钮。
- 服务器运行是带有用户参数的外部程序。
- 当程序 returns 时,服务器获取输出(XML 文件)并放入 数据库中的内容。
- 服务器随后使用来自数据库的结果更新客户端。
需要注意的是,用户可以同时运行多个外部程序,参数不同。
当外部程序完成时,我应该如何更新客户端(Web GUI):是否必须由客户端轮询更新(例如,通过查看数据库是否结果在这里)?或者有没有办法 "push" 从服务器到客户端?
我也在查看设计示例以实现此目的,因此请随时提供有关此体系结构的建议和资源。
我开始在我的应用程序中使用队列,我和你有同样的问题。
我认为(但仍未尝试)的一个解决方案是在用户启动此类异步进程时启动套接字(使用 socket.io)并发送回调 url(指向您的快递服务器)到流程。 回调将有一个 client/session id 参数来标识发出请求的人并选择正确的套接字将消息推回。 使用套接字,您不必从客户端到服务器进行池化。
我觉得这叫Pub/Sub。 Redis 等一些技术也可以帮助实现它。
我也想收到有关此方法的反馈。你怎么看?
好的,看来您需要两种类型的更新。
1) 当外部程序执行完毕
...你需要告诉快递服务器发生了什么以及结果。这里最简单的方法是简单地在 express 的 public(或私有)API 上点击一个方法,它已经有了。
例如,使用 request library:
var request = require('request');
var EXPRESS_URL = 'http://localhost:8080/api/task'
//...
// This is called after you save results to database
function onTaskCompleted(taskId, result) {
request.put(
{
url: EXPRESS_URL + '/' + taskId,
json: result
},
function (err, httpResponse, body) {
// Handle response
}
);
}
如果这些服务器不在同一台机器上,您还需要在您的 express 服务器中有相应的 /api/task/:id/
路由和一些安全措施。
2) 当 express server 发现一个任务已经完成时
...您需要通知当前活跃的用户。在这种情况下,这将发生在 /api/task/:id/
请求处理程序中。从这里通知用户浏览器的最佳方式是通过 socket.io。在 node 中安装真的很容易,并且会解决所有遗留浏览器问题。
在服务器上,你可以这样使用它:
app.put('/api/task/:id', function (req, res) {
var payload = {
id: req.params.id,
result: req.data
};
io.emit('task_completed', payload);
});
在客户端:
io.on('task_completed', function (data) {
alert('Task ' + data.id + ' has finished with result ' + data.result);
});
您肯定想使用 Socket.io,正如 Tulio 所建议的。您特别询问了如何更新客户端的想法,所以我假设您知道如何知道服务器何时执行完外部程序。
websocket 允许您的服务器随时将数据发送回客户端,例如当您的程序完成时。它消除了您使用长轮询或 ajax 技术的需要,这些技术可能会比您希望的占用更多的开发周期。
Socket.io 是 最好、最受欢迎的 websocket 包装器之一。它是跨浏览器的,甚至移动支持也是无与伦比的。基本上,如果你是 运行 一个 node.js 服务器,你想使用 socket.io。
这是我昨晚推荐给一位同事的很棒的教程:
https://nodesource.com/blog/understanding-socketio
而且,为了节省您大量的搜索时间,我想我还要提到创建跨文件客户端套接字。您只需在主 html 文件中声明套接字变量:
index.html:
<html>
<script src="https://cdn.socket.io/socket.io-1.3.4.js"></script>
<script>
var socket;
var connected=false;
</script>
</html>
main.js:
socket = io.connect('http//localhost'); //Make sure you include http//
socket.on('connect'){
connected = true;
});
secondary.js:
setInterval(function(){
if(connected === true){
socket.emit('doesThisWork', true);
};
}, 100);
此外,要强制建立新连接,您可以:
socket = io.connect('http//localhost', {'force new connection': true);
为了确保套接字安全,您需要保护您的 url... 例如HTTPS 也能确保您的套接字安全。