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

声明:本页面是StackOverFlow热门问题的中英对照翻译,遵循CC BY-SA 4.0协议,如果您需要使用它,必须同样遵循CC BY-SA许可,注明原文地址和作者信息,同时你必须将它归于原作者(不是我):StackOverFlow 原文地址: http://stackoverflow.com/questions/16866015/
Warning: these are provided under cc-by-sa 4.0 license. You are free to use/share it, But you must attribute it to the original authors (not me): StackOverFlow

提示:将鼠标放在中文语句上可以显示对应的英文。显示中英文
时间:2020-09-02 14:40:55  来源:igfitidea点击:

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

javascriptnode.jsapihttprest

提问by Rob

I am using express module to make a Restful API within Node.JS. 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.

我正在使用 express 模块在 Node.JS 中创建一个 Restful API。在我的服务中,我向外部端点(服务器端)发出额外的 http 请求,我需要将这些 http 请求中的数据返回到我的 Web 服务请求正文。

I have confirmed that if I use console.logon all the actions that the Web Service is conducting I am getting the data that I need. However, when I try to Return those values to the service they come back Null. I know that this is because of async and the callback is not waiting for the http request to finish.

我已经确认,如果我console.log对 Web 服务正在执行的所有操作使用,我将获得我需要的数据。但是,当我尝试将这些值返回给服务时,它们返回 Null。我知道这是因为异步并且回调没有等待 http 请求完成。

Is there a way to make this work?

有没有办法使这项工作?

回答by Daniel

A common practice is to use the asyncmodule.

通常的做法是使用async模块。

npm install async

The asyncmodule has primitives to handle various forms of asynchronous events.

async模块具有处理各种形式的异步事件的原语。

In your case, the async#parallelcall 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 requestmodule helpful as well.

由于您正在发出外部 http 请求,您可能会发现请求模块也很有帮助。

npm install request

Using requestand async#parallelyour 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.

您还可以在此处阅读其他回调排序方法。

回答by Oved D

Node.js is all about callbacks. 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

Node.js 是关于回调的。除非 API 调用是同步的(罕见且不应完成),否则您永远不会从这些调用中返回值,而是使用回调方法中的结果进行回调,或调用快速方法 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:

让我们以一个非常简单的例子来调用 google。使用 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);
    }
  })
}

回答by Lucio M. Tato

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