【问题标题】:Node.js wait for callback of REST service that makes HTTP requestNode.js 等待发出 HTTP 请求的 REST 服务的回调
【发布时间】:2021-05-10 07:15:35
【问题描述】:

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

通过使用console.log(),在 Web 服务正在执行的所有操作上,我已确认我获得了所需的数据。但是,当我尝试将这些值返回给服务时,它们会返回值null。我知道这是因为请求是异步的,并且回调没有等待 HTTP 请求完成。

有没有办法让它工作?

【问题讨论】:

  • 您需要接受回调。
  • 我认为你在等待响应,而不是回调。

标签: javascript node.js http rest


【解决方案1】:

一种常见的做法是使用async 模块。

npm install async

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

在您的情况下,async#parallel 调用将允许您同时向所有外部 API 发出请求,然后合并结果以返回给请求者。

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

npm install request

使用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]});
  }
  );
};

您还可以阅读其他回调排序方法here

【讨论】:

【解决方案2】:

Node.js 都是关于回调的。除非 API 调用是同步的(罕见且不应该这样做),否则您永远不会从这些调用中返回值,而是使用回调方法中的结果进行回调,或者调用 express 方法 res.send

request.js 是一个很好的调用 Web 请求的库

让我们以调用 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);
    }
  })
});

或者,您可以将回调传递给调用 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);
    }
  })
}

【讨论】:

【解决方案3】:

等待。 https://github.com/luciotato/waitfor

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

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 2016-05-20
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2021-10-10
    • 1970-01-01
    • 2020-07-12
    • 2017-07-30
    相关资源
    最近更新 更多