Reputation: 351
NodeJS 6.9.3
I wrote a simple NodeJS app that makes a request that looks like this:
var http_request = require('request')
http_request(
{ method: 'GET'
, uri: 'https://search-xxxxxx.us-east-1.es.amazonaws.com/facts/_search?pretty=true'
, 'content-type': 'application/json'
, body: es_regexp_query_as_string
}
, function (error, response, body) {
if(
response.statusCode == 201
||
response.statusCode == 200) {
And it works great. I do whatever I need to do in the callback. However, now I need to re-architect this app, so that instead of doing one HTTP request, it can do an arbitrary number of requests. As I understand it, the ideal "design pattern" for handling this in NodeJS is to wrap each request in a Promise, and then hand all the Promises to a call to:
Promise.all(something)
But I've been reading on this, and I can not find out how to transform the HTTP requests into Promises. Or rather, there is a ton of conflicting advice. Apparently the concept of "Promise" has changed a lot in NodeJS, just over the last year or two.
I tried to simply wrap the whole code block in a Promise, but that did not work. So what do I do?
Upvotes: 0
Views: 4273
Reputation: 777
If you want a solution without any external module, check this code:
// Dependencies
var http = require('http');
var https = require('https');
var httpRequest = function(options){
if(!options) return new Promise((_, reject)=>{ reject( new Error('Missing \'options\' arg.'))})
if(!options.host) return new Promise((_, reject)=>{ reject( new Error('\'host\' parameter is empty.'))})
var protocol = (options.protocol || 'http').toLowerCase();
var method = (options.method || 'GET').toUpperCase();
var path = options.path || '/';
var port = options.port || (protocol == 'https' ? 443 : 80);
var _http = protocol == 'https'? https : http;
var prom = new Promise((resolve, reject)=>{
var ops = {
host : options.host, // here only the domain name
port : port,
path : (/^(\/)/i.test(path) ? '' : '/' ) + path,
headers: options.headers || {},
method : method
};
var body = options.body;
if(body && typeof(body) === 'object'){
body = JSON.stringify(body);
if(!utils.hasHeader(ops, 'Content-Type')) ops.headers['Content-Type'] = 'application/json; charset=utf-8';
if(!utils.hasHeader(ops, 'Content-Length')) ops.headers['Content-Length'] = Buffer.byteLength(body, 'utf8');
}
var req = _http.request(ops, (res)=>{
var decoder = new StringDecoder('utf-8');
var buffer = '';
res.on('data', function(data) {
buffer += decoder.write(data);
});
res.on('end', function() {
buffer += decoder.end();
if(/^(2)/i.test(res.statusCode.toString()))
resolve({statusCode : res.statusCode , data : buffer })
else
reject({statusCode : res.statusCode , error : buffer })
});
req.on('error', (err)=>{
reject({statusCode : 0, error : err});
})
req.on('timeout', (err)=>{
reject({statusCode : 0, error : new Error('Timeout exeded.')});
})
if(body) req.write(Buffer.from(body).toString('utf8'));
req.end();
});
return prom;
}
Upvotes: 2
Reputation: 99728
Instead of request-promise
, you might also consider node-fetch
as an alternative. This package implements the Fetch API which is likely to be the future of doing HTTP requests on both servers and clients, and it 100% assumes promises and it's a bit less messy than that request library.
Upvotes: 0