Monday 25 November 2019

node.js - Express.js: res.render() does not send data when wrapped in promise chain

I recently started refactoring older callback-hell routes to use promises. (Note: the refactor is not complete so some of the following code is ugly)




Doing so broke my res.render() function.




  • I am using EJS for my render engine.

  • Most of my promise chains are built off of MongoDB / Mongoose queries.



The basic app structure is a complex survey / quiz that sorts users into different categories. It stores their info and renders a custom EJS page at the end. Here's how the final call works, basically:



         mongoose.model('Result')

.findOne({quizId: req.query.id})
.then(getPageData)
.then(renderPage)
.catch(errorHandler)


Simple enough, in theory.



Relevant functions:




    let getPageData = (mongooseResult) => {

let resultsPage;
let analyticsData;

if (mongooseResult.answers.section1.question1.answer != null && mongooseResult.answers.section1.question1.answer != undefined){
let resultsPage = WP.getPage(wp_pages_data, 'slug', mongooseResult.coreFit);
let analyticsData = {
quizId: mongooseResult.quizId,
coreFit: mongooseResult.coreFit,

secondFit: mongooseResult.secondFit,
degree: mongooseResult.answers.section1.question1.answer,
year: mongooseResult.answers.section1.question2.answer,
concentration: mongooseResult.answers.section1.question3.answer,
views: mongooseResult.views,
}

mongooseResult.views++;
mongooseResult.save();


return [resultsPage, analyticsData, mongooseResult];
} else {
throw new Error('S1Q1 IS UNDEFINED');
}
};
let renderPage = ([resultsPage, analyticsData, mongooseResult]) => {
if (resultsPage != null && resultsPage != undefined){

// WHY IS MY RENDER NOT WORKING???
res.render('templates/' + mongooseResult.coreFit, Object.assign({}, WP.get_WP_data(resultsPage), getPartials(mongooseResult.modules), analyticsData), (err, html) => {if (err) console.log(err); else res.send(html);});

} else {
throw new Error('GETTING PAGE DATA RETURNED UNDEFINED');
}
};


Incoming requests are first routed to a /submit POST route - which manipulates some data, stores it all in the DB, then does res.redirect() to the /results?id=12345 GET route, which runs the logic above.



What's funky is that the render() actually fires; the callback ( (err, html) => {if (err) console.log(err); else res.send(html);} ) sends rendered HTML to IF YOU HIT THE ROUTE A SECOND TIME.




Completing the survey does NOT generate a response; but it DOES successfully store all our info in the DB and console.logs the ID to which the client request should redirect. Hitting the GET route with this generated ID / URL, literally by copy-pasting it, renders just fine.



Swapping the render for a simple res.send('wtf') works - an actual response is sent to the client. (in this case the string 'wtf' ... )



The response just doesn't send back data. I don't get it. Any ideas?



UPDATE:
Strangely enough, hitting the route manually vs the redirect from my earlier POST request produce different results with a simple res.send('wtf mate').



Hitting the GET route and passing in a previously existing ID to the req.query manually:enter image description here




Hitting the GET route AFTER the res.redirect() call from the prior POST request:enter image description here



This might be more an Express request type mismatch issue? Why would a res.redirect('/results?id=someString') call mutate the URL vs sending back a string / HTML?

No comments:

Post a Comment

php - file_get_contents shows unexpected output while reading a file

I want to output an inline jpg image as a base64 encoded string, however when I do this : $contents = file_get_contents($filename); print &q...