最新消息:雨落星辰是一个专注网站SEO优化、网站SEO诊断、搜索引擎研究、网络营销推广、网站策划运营及站长类的自媒体原创博客

javascript - Express.js res.render() and res.redirect() - Stack Overflow

programmeradmin1浏览0评论

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 pleted (OK)
  • When all calculations are pleted, 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.

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 pleted (OK)
  • When all calculations are pleted, 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.
Share Improve this question edited Nov 16, 2018 at 16:15 Jonathan Hall 80k19 gold badges160 silver badges204 bronze badges asked Mar 1, 2016 at 10:35 bitstreambitstream 1,1162 gold badges19 silver badges30 bronze badges
Add a ment  | 

2 Answers 2

Reset to default 4

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./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!

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

发布评论

评论列表(0)

  1. 暂无评论