Подтвердить что ты не робот

Node.JS Ждите обратного вызова службы REST, которая делает запрос HTTP

Я использую экспресс-модуль для создания Restful API в Node.JS. В моем сервисе я делаю дополнительные HTTP-запросы для внешних конечных точек (на стороне сервера), и мне нужно вернуть данные из этих http-запросов в тело запроса веб-службы.

Я подтвердил, что если я использую console.log для всех действий, которые проводит веб-служба, я получаю нужные мне данные. Однако, когда я пытаюсь вернуть эти значения в службу, они возвращаются Null. Я знаю, что это из-за async, и обратный вызов не ждет завершения HTTP-запроса.

Есть ли способ сделать эту работу?

4b9b3361

Ответ 1

Общей практикой является использование модуля async.

npm install async

Модуль async имеет примитивы для обработки различных форм асинхронных событий.

В вашем случае вызов async#parallel позволит вам одновременно отправлять запросы ко всем внешним API-интерфейсам, а затем объединять результаты для запроса реквестера.

Поскольку вы делаете внешние HTTP-запросы, вы, вероятно, найдете request модуль.

npm install request

Используя request и async#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]});
  }
  );
};

Вы также можете прочитать о других методах упорядочения обратного вызова здесь.

Ответ 2

Node.js - все о обратных вызовах. Если вызов API не является синхронным (редко и не должен выполняться), вы никогда не возвращаете значения из этих вызовов, а обратный вызов с результатом из метода обратного вызова или вызываете экспресс-метод res.send

Большая библиотека для вызова веб-запросов - request.js

Возьмем действительно простой пример вызова 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);
    }
  })
});

В качестве альтернативы вы можете передать обратный вызов методу, который вызывает веб-запрос, и вызвать этот обратный вызов из этого метода:

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

Wait.for https://github.com/luciotato/waitfor

Другие примеры ответов с использованием wait.for:

Пример из ответа Daniel (асинхронный), но используя 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);
            });
}