简体   繁体   English

Node.JS等待发出HTTP请求的REST服务的回调

[英]Node.JS Wait for callback of REST Service that makes HTTP request

I am using express module to make a Restful API within Node.JS. 我正在使用express模块​​在Node.JS中创建Restful API。 In my service I am making additional http requests to outside Endpoints(server side) and I need to return the data from those http requests to my web service request body. 在我的服务中,我正在向外部端点(服务器端)发出额外的http请求,我需要将这些http请求中的数据返回给我的Web服务请求体。

I have confirmed that if I use console.log on all the actions that the Web Service is conducting I am getting the data that I need. 我已经确认,如果我在Web服务正在执行的所有操作上使用console.log ,我将获得所需的数据。 However, when I try to Return those values to the service they come back Null. 但是,当我尝试将这些值返回给服务时,它们会返回Null。 I know that this is because of async and the callback is not waiting for the http request to finish. 我知道这是因为异步并且回调不等待http请求完成。

Is there a way to make this work? 有没有办法让这项工作?

A common practice is to use the async module. 通常的做法是使用异步模块。

npm install async

The async module has primitives to handle various forms of asynchronous events. async模块具有处理各种形式的异步事件的原语。

In your case, the async#parallel call will allow you to make requests to all external APIs at the same time and then combine the results for return to you requester. 在您的情况下, async#parallel调用将允许您同时向所有外部API发出请求,然后将结果组合以返回给您的请求者。

Since you're making external http requests, you will probably find the request module helpful as well. 由于您正在进行外部http请求,因此您可能会发现请求模块也很有用。

npm install request

Using request and async#parallel your route handler would look something like this... 使用requestasync#parallel您的路由处理程序看起来像这样......

var request = require('request');
var async = require('async');

exports.handler = function(req, res) {
  async.parallel([
    /*
     * First external endpoint
     */
    function(callback) {
      var url = "http://external1.com/api/some_endpoint";
      request(url, function(err, response, body) {
        // JSON body
        if(err) { console.log(err); callback(true); return; }
        obj = JSON.parse(body);
        callback(false, obj);
      });
    },
    /*
     * Second external endpoint
     */
    function(callback) {
      var url = "http://external2.com/api/some_endpoint";
      request(url, function(err, response, body) {
        // JSON body
        if(err) { console.log(err); callback(true); return; }
        obj = JSON.parse(body);
        callback(false, obj);
      });
    },
  ],
  /*
   * Collate results
   */
  function(err, results) {
    if(err) { console.log(err); res.send(500,"Server Error"); return; }
    res.send({api1:results[0], api2:results[1]});
  }
  );
};

You can also read about other callback sequencing methods here . 您还可以在此处阅读其他回调排序方法。

Node.js is all about callbacks. Node.js就是回调。 Unless the API call is synchronous (rare and shouldn't be done) you never return values from those calls, but callback with the result from within the callback method, or call the express method res.send 除非API调用是同步的(很少见且不应该完成),否则永远不会从这些调用中返回值,而是使用回调方法中的结果回调,或者调用express方法res.send

A great library for invoking web requests is request.js 用于调用Web请求的一个很棒的库是request.js

Let's take the really simple example of calling google. 让我们来看看调用谷歌这个非常简单的例子吧。 Using res.send, your express.js code could look like: 使用res.send,您的express.js代码可能如下所示:

var request = require('request');
app.get('/callGoogle', function(req, res){
  request('http://www.google.com', function (error, response, body) {
    if (!error && response.statusCode == 200) {
      // from within the callback, write data to response, essentially returning it.
      res.send(body);
    }
  })
});

Alternatively, you can pass a callback to the method that invokes the web request, and invoke that callback from within that method: 或者,您可以将回调传递给调用Web请求的方法,并从该方法中调用该回调:

app.get('/callGoogle', function(req, res){
  invokeAndProcessGoogleResponse(function(err, result){
    if(err){
      res.send(500, { error: 'something blew up' });
    } else {
      res.send(result);
    }
  });
});

var invokeAndProcessGoogleResponse = function(callback){
  request('http://www.google.com', function (error, response, body) {

    if (!error && response.statusCode == 200) {
      status = "succeeded";
      callback(null, {status : status});
    } else {
      callback(error);
    }
  })
}

Wait.for https://github.com/luciotato/waitfor 等等。访问https://github.com/luciotato/waitfor

Other answer's examples using wait.for: 使用wait.for的其他答案示例:

Example from from Daniel's Answer (async), but using Wait.for 来自Daniel's Answer(async)的示例,但使用Wait.for

var request = require('request');
var wait = require('wait.for');

exports.handler = function(req, res) {
try {  
    //execute parallel, 2 endpoints, wait for results
    var result = wait.parallel.map(["http://external1.com/api/some_endpoint"
                 ,"http://external2.com/api/some_endpoint"]
                 , request.standardGetJSON); 
    //return result
    res.send(result);
}
catch(err){
    console.log(err); 
    res.end(500,"Server Error")
}
};

//wait.for requires standard callbacks(err,data)
//standardized request.get: 
request.standardGetJSON = function ( options, callback) {
    request.get(options,
            function (error, response, body) {
                //standardized callback
                var data;
                if (!error) data={ response: response, obj:JSON.parse(body)};
                callback(error,data);
            });
}

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM