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:

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' ... )

why You pass anonymous function as last argument? res.render and sends it to client. I don't see necessity to do additional res.send.
– num8erJun 5 '17 at 17:35

You're right - In this case for debugging only; I wanted to see whether adding the extra callback explicitly did anything to help - or if there was a secret err being swallowed behind the scenes.
– ZfalenJun 5 '17 at 17:43

Since you're using code like mongooseResult.save(), are you sure that the POST /submit actually waits for the database saves/updates to be completed before it redirects?
– robertklepJun 5 '17 at 18:52

2 Answers
2

Based on your update, it sounds like your res.send() call is being interpreted strangely on the client side. POST request should not affect the URL bar unless you've specifically told it to - have you checked where the client initially sends this request?

My guess - since you say that the routing code you posted above is being hit from res.redirect() on a prior POST route - is that there is client-side logic expecting a response object to be a URL string, and hitting the GET route for the first time via your redirect carries over this response object. So that the client is attempting to insert a massive string of HTML into the URL bar.

In this case, hitting the GET route manually, like you said, would simply render the HTML from res.render() by default - but your initial hit from the res.redirect() might not.

DOH! You nailed it.... Here is part of my client-side AJAX: success: (res) => { window.location = res; } So, yeah, you're right. Since res.render() returns an HTML string, the URL bar didn't have a clue what to do with it. But the default GET behavior expects HTML - so manually pinging the route behaved correctly. Instead of doing res.redirect(), I just did a res.send('results?id=12345') - which redirects the client to my GET route and it all is well with the world! Thanks!
– ZfalenJun 5 '17 at 21:08

Thanks for the response, @num8er ! Turns out it was a terrible client-side oversight on my part during the refactor process. Check out Lars' answer above - the critical clue was how my URL bar re-routed when hitting the GET route as part of a redirect when submitting the final survey.... Totally spaced this piece since 99% of the refactor is server-side
– ZfalenJun 5 '17 at 21:11