Express.js res.render() and res.redirect()
我的快速应用程序中有一条路线,应该执行以下操作:
- 从外部获取一些数据(确定)
- 显示带有socket.io的HTML页面以侦听消息(确定)
- 执行一些计算,这需要很长时间
- 每完成一个操作,就通过socket.io发送一条消息(确定)
- 完成所有计算后,显示结果页面(问题)
因此,我的代码的简化版本是:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 | module.exports = function(io) { // This is so I can use socket.io inside the route var express = require('express'); var router = express.Router(); [... and other required] router.post('/', function(req, res, next) { res.render('loading'); // This renders the template which holds accepts and renders socket.io messages pefromCalculaton(); sendSocketIOMessage(); session.data = resultData; // I get the result of all calculations and put that in the session. It's a quick fix, don't judge, I've got no presistancy in my project as for now... res.redirect('results'); // And here I'd like to go to the other route, which will display the data, getting it from the session. }); return router; } |
因为这行不通,所以我可能试图在这里做一些真正愚蠢的事情。但是我真正想做的是:
- 执行计算
- 在执行计算时,使用套接字更新进度
- 计算完成后,渲染一个模板,显示所有结果。
好吧,我的朋友,正如您所知,一个请求中的一个不能发送两个响应。所以这是您需要做的。
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 | module.exports = function(io) { // This is so I can use socket.io inside the route var express = require('express'); var router = express.Router(); [... and other required] router.post('/', function(req, res, next) { var taskId = (new Date()).getTime(); //timestamp to get unique task id. res.render('loading'); startCalculations(function(progressIndicator){ //progress callback io.emit('progress',progressIndicator); },function(result){ // Finish callback session[taskId] = result; io.emit('finish',{ taskid: taskId }); }); }); router.get('/result:taskId', function(req, res, next) { var result = session[req.params.taskId]; if(!result) { //Result already consumed! res.render('expired'); return; } delete session[req.params.taskId]; res.render('result', {result: result}); }); //progress callback will be called when we want to report progress //done callback indicates our results are ready. function startCalculations(progress, done){ //This is just a stupid piece of code, just to emulate loading. //Your awesome async code will replace this //In your case it will not be a loop and there will be a callback //To signal finish. var result = 0; for(i = 0; i < 100; i++) { result = result + i; //Simulate progress progress(i); } //Simulate finish -- result has 0 to 99 all added up ;) done(result); } return router; } |
现在在html前面您可以拥有...
this is how your
loading view would look like.
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 | <script src="/socket.io/socket.io.js"> <script src="http://code.jquery.com/jquery-1.11.1.js"> var socket = io(); //Init code. socket.on('progress', function(progressIndicator){ //Your jquery mojo to show progress displayProgress(progressIndicator); }); socket.on('finish', function(task){ //Redirect to result page from frontend (you were trying to do //on backend -- node.js) window.location.href="/result/" + task.taskId; //OR //window.location.replace("/result/" + task.taskId); }); |
希望这是有道理的,对您有帮助...
让我知道您是否还有其他需要。
玩得开心!
节点是异步的。使用回调或Promise确保仅在计算完成后才显示结果页面。