在NodeJS中,如何将HTTP请求包装到Promises中?

时间:2017-11-01 17:49:51

标签: node.js promise httprequest

NodeJS 6.9.3

我写了一个简单的NodeJS应用程序,它发出如下所示的请求:

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) {

它很棒。我在回调中做任何我需要做的事情。但是,现在我需要重新构建此应用程序,以便它可以执行任意数量的请求,而不是执行一个HTTP请求。据我了解,在NodeJS中处理这个问题的理想“设计模式”是将每个请求包装在Promise中,然后将所有Promise交给调用:

Promise.all(something)

但我一直在阅读,我无法找到如何将HTTP请求转换为Promises。或者更确切地说,存在大量相互矛盾的建议。显然,在过去的一两年里,NodeJS中的“Promise”概念发生了很大变化。

我试图简单地将整个代码块包装在Promise中,但这不起作用。那我该怎么办?

3 个答案:

答案 0 :(得分:2)

我建议您使用已经解决了问题的请求承诺(https://github.com/request/request-promise)。

答案 1 :(得分:0)

您可以考虑使用request-promise替代node-fetch,而不是make。这个软件包实现了Fetch API,这可能是在服务器和客户端上执行HTTP请求的未来,它100%承担承诺,并且它比该请求库稍微麻烦。

答案 2 :(得分:0)

如果您想要不带任何外部模块的解决方案,请检查以下代码:

// 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;
}