javascript - How to render rest api call in node.js with express and handlebar or other template engine? -
use case
using node.js, express , template engine handlebars query rest apis wordpress , couchdb , render results.
i have come far
var https = require('https'); var express = require('express'); var handlebars = require('express-handlebars') .create({ defaultlayout:'main' }); var app = express(); app.engine('handlebars', handlebars.engine); app.set('view engine', 'handlebars'); app.set('port', process.env.port || 3000); app.set('ip', process.env.ip); var options = { hostname: 'public-api.wordpress.com', path: '/rest/v1.1/sites/somesite.wordpress.com/posts/16', method: 'get' }; app.get('/test', function(req, res) { https.request(options, function(restres) { console.log('status: ' + restres.statuscode); res.render('home', { "title": "test" }); // code works. restres.on('data', function (jsonresult) { // res.render('home', { "title": "test" }); code (after removing line above) not work. console.log('body: ' + jsonresult); }); }).end(); }); app.listen(app.get('port'), app.get('ip'), function(){ console.log( 'express started on http://' + app.get('ip') + ": " + app.get('port') + '; press ctrl-c terminate.' ); });
this code works , jsonresult show correcty @ console. moving line res.render('home', { "title": "test" });
inside restres.on('data', function (jsonresult)
callback throws error.
error: can't set headers after sent. @ serverresponse.outgoingmessage.setheader (_http_outgoing.js:331:11) @ serverresponse.header (/home/ubuntu/workspace/node_modules/express/lib/response.js:718:10) @ serverresponse.send (/home/ubuntu/workspace/node_modules/express/lib/response.js:163:12) @ res.render.done (/home/ubuntu/workspace/node_modules/express/lib/response.js:957:10) @ immediate._onimmediate (/home/ubuntu/workspace/node_modules/express-handlebars/lib/utils.js:26:13) @ processimmediate [as _immediatecallback] (timers.js:374:17)
do oversee obvious error? how right way?
the error self-explanatory, cannot set header when response sent. error happen due following
cause 1
the following fails because try send response more once.
//the following lines send response res.render('home', { "title": "test" }); // code works. restres.on('data', function (jsonresult) { //you have send response above, hence error res.render('home', { "title": "test" }); code (after removing line above) not work. console.log('body: ' + jsonresult); });
cause 2
this fails , shows error because, .on('data')
called more once (depending on size of response) , because data returned in chunks hence, trying res.render
multiple times.
restres.on('data', function (jsonresult) { res.render('home', { "title": "test" }); console.log('body: ' + jsonresult); });
possible solution
you need use .on('data')
receive chunks , build entire response here , use .on('end')
res.render
complete response. follow:
var body = ''; //use chunks build whole response body variable restres.on('data', function (chunk) { body += chunk; }); //this called when request finished , response returned //hence, use constructed body string parse json , return restres.on('end', function () { console.log('whole response > ' + body); var jsonobject = json.parse(body); res.render('home', {data:jsonobject}); //in view use data json object. });
another possible solution rather concatenating chunks returned .on('data')
, can push them in array , in .on('end')
join array elements construct response body , parse json , return it. sample below:
var body = []; restres.on('data', function(chunk) { body.push(chunk); }); restres.on('end', function() { //joined chunks var result = json.parse(data.join('')) res.render('home', {data: result}); });
Comments
Post a Comment