nodejs https callback not updating global variable

2019-09-04 17:29发布

问题:

This question already has an answer here:

  • How do I return the response from an asynchronous call? 35 answers

I'm setting up a quick proxy server in nodejs to proxy a API request for an Angular application. The proxy endpoint is a service I do not control and does not support CORS or JSONP. For testing, I setup a dummy http server in the code example below, but in reality this is a remote domain.

I'm pretty sure my problem is due to asynchronous processing of nodejs, but I don't know how to solve this. My generic makeRequest() function seems to work ok, it gets the expected response back from the remote server. I can see the resultData string in the on('data') and on('end') event handlers with success. However, I don't know how to get the response back to the browser inside restify's req.json() method.

Help!

var restify = require('restify');
var querystring = require('querystring');
var https = require('https');
var http = require('http');
var port        =  '8080';
var server = restify.createServer({
    name : "ProxyService"
});
var responseData = '';

// Generic request function
function makeRequest(host, endpoint, method, data, headers) {
    var dataString = JSON.stringify(data);

    var options = {
      host: host,
      path: endpoint,
      method: method,
      headers: headers
    };

    var req = https.request(options, function proxyrespond(res) {

      res.on('data', function(data) {
        console.log("DATA----", data);
        responseData += data;
      });

      res.on('end', function() {
        //probably need to do something here
      });
    });
    req.end();
    req.on('error', function(e) {
        console.error(e);
    });

    console.log("OPTIONS: ", options);
    console.log("DATA: ", responseData);
    req.write(dataString);
    req.end();
};

server.get('/getlist', function respond(req, res, next){
    var headers     =  {'Connection': 'close',
                        'Content-Type': 'application/json' };
    var host = 'localhost:9000';
    var endpoint = '/getlist';
    var auth = {auth-id: '12345', auth-token: '6789'}
    var data = req.data || '';

    // add authentication parms to the endpoint
    endpoint += '?' + querystring.stringify(auth);

    // if the request has headers, add them to the object
    for (var key in res.headers) {
        headers[key] = rest.headers[key];
    };

    makeRequest(host, endpoint, 'GET', data, headers);
    res.headers = {Connection: 'close'};
    res.json( responseData );
    return next();
});

http.createServer(function (req, res) {
  res.writeHead(200, { 'Content-Type': 'text/plain' });
  res.write('request successfully proxied!' + '\n' + JSON.stringify(req.headers, true, 2));
  res.end();
}).listen(9000);

server.listen(port, function(){
    console.log('%s listening at %s ', server.name , server.url);
});

回答1:

Return via a callback function:

// Generic request function
function makeRequest(host, endpoint, method, data, headers, callback) {
    .........
    var req = https.request(options, function proxyrespond(res) {
      // DO NOT declare responseData as global variable
      var responseData = '';
      res.on('data', function(data) {
        responseData = responseData + data;
      });

      res.on('end', function() {
        // RETURN VIA CALLBACK
        callback(responseData)
      });
    });
    .........
};

server.get('/getlist', function respond(req, res, next){
    .........

    makeRequest(host, endpoint, 'GET', data, headers, function (responseData) {
        res.headers = {Connection: 'close'};
        res.json( responseData );
        return next();
    });

});