Express.js res.render() and res.redirect()

点点圈 提交于 2019-12-07 20:26:24

问题


I have a route in my express app, which is supposed to do the following:

  • Get some data from outside (OK)
  • Show a HTML page with socket.io listening for messages (OK)
  • Perform some calculations, which take a long time
  • Send a message trough socket.io after each one one completed (OK)
  • When all calculations are completed, show a result page (problem)

So, a simplified version of my code is:

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;
}

Since this doesn't work, I am probably trying to do something really stupid here. But what I actually want to do is:

  • Perform calculations
  • While performing the calculations, update progress using sockets
  • When calculation is done, render a template, showing all the results.

回答1:


Well, my friend, as you know that one can't send two responses from within one request. So here is what you need to do.

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;
}

Now on the html front you can have ...

this is how your loading view would look like.

<script src="/socket.io/socket.io.js"></script>
<script src="http://code.jquery.com/jquery-1.11.1.js"></script>
<script>
  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);
  });
</script>

Hope this makes sense and helps ...

Let me know if you need anything else.

Have fun!




回答2:


Node is asynchronous. Use callbacks or promises to make sure that the result page is shown only when the calculations has been completed.



来源:https://stackoverflow.com/questions/35720587/express-js-res-render-and-res-redirect

易学教程内所有资源均来自网络或用户发布的内容,如有违反法律规定的内容欢迎反馈
该文章没有解决你所遇到的问题?点击提问,说说你的问题,让更多的人一起探讨吧!