[node.js] Node.js의 동기 요청

3 http API를 순차적으로 호출해야하는 경우 다음 코드에 대한 더 나은 대안은 무엇일까요?

http.get({ host: 'www.example.com', path: '/api_1.php' }, function(res) { 
  res.on('data', function(d) { 

    http.get({ host: 'www.example.com', path: '/api_2.php' }, function(res) { 
      res.on('data', function(d) { 

        http.get({ host: 'www.example.com', path: '/api_3.php' }, function(res) { 
          res.on('data', function(d) { 


          });
        });
        }
      });
    });
    }
  });
});
}



답변

사용 deferreds 좋아 Futures.

var sequence = Futures.sequence();

sequence
  .then(function(next) {
     http.get({}, next);
  })
  .then(function(next, res) {
     res.on("data", next);
  })
  .then(function(next, d) {
     http.get({}, next);
  })
  .then(function(next, res) {
    ...
  })

범위를 전달해야하는 경우 다음과 같이하십시오.

  .then(function(next, d) {
    http.get({}, function(res) {
      next(res, d);
    });
  })
  .then(function(next, res, d) { })
    ...
  })


답변

나는 Raynos의 솔루션도 좋아하지만 다른 흐름 제어 라이브러리를 선호합니다.

https://github.com/caolan/async

각 후속 함수에서 결과가 필요한지 여부에 따라 직렬, 병렬 또는 폭포수를 사용합니다.

직렬로 실행해야하는 경우 시리즈 이지만 이후의 각 함수 호출에서 결과가 반드시 필요하지는 않습니다.

병렬 로 실행할 수있는 경우 병렬 로 실행할 수있는 경우 각 병렬 함수에서 각각의 결과가 필요하지 않으며 모두 완료되면 콜백이 필요합니다.

각 함수에서 결과를 모핑하고 다음으로 전달하려는 경우 폭포

endpoints =
 [{ host: 'www.example.com', path: '/api_1.php' },
  { host: 'www.example.com', path: '/api_2.php' },
  { host: 'www.example.com', path: '/api_3.php' }];

async.mapSeries(endpoints, http.get, function(results){
    // Array of results
});


답변

공통 노드 라이브러리를 사용하여이 작업을 수행 할 수 있습니다 .

function get(url) {
  return new (require('httpclient').HttpClient)({
    method: 'GET',
      url: url
    }).finish().body.read().decodeToString();
}

var a = get('www.example.com/api_1.php'),
    b = get('www.example.com/api_2.php'),
    c = get('www.example.com/api_3.php');


답변

동기화 요청

지금까지 내가 찾아서 사용한 가장 쉬운 방법은 sync-request 이며 노드와 브라우저를 모두 지원합니다!

var request = require('sync-request');
var res = request('GET', 'http://google.com');
console.log(res.body.toString('utf-8'));

그것이 lib 폴 백이 있지만 미친 구성이나 복잡한 lib 설치가 아닙니다. 그냥 작동합니다. 여기에서 다른 예제를 시도해 보았고 할 일이 많거나 설치가 작동하지 않을 때 당황했습니다!

노트:

sync-request가 사용 하는 예제 는를 사용할 때 잘 작동하지 않으며 res.getBody()get body가 수행하는 모든 작업은 인코딩을 수락하고 응답 데이터를 변환하는 것입니다. 그냥 할 res.body.toString(encoding)대신.


답변

API 목록과 함께 재귀 함수를 사용합니다.

var APIs = [ '/api_1.php', '/api_2.php', '/api_3.php' ];
var host = 'www.example.com';

function callAPIs ( host, APIs ) {
  var API = APIs.shift();
  http.get({ host: host, path: API }, function(res) {
    var body = '';
    res.on('data', function (d) {
      body += d;
    });
    res.on('end', function () {
      if( APIs.length ) {
        callAPIs ( host, APIs );
      }
    });
  });
}

callAPIs( host, APIs );

편집 : 버전 요청

var request = require('request');
var APIs = [ '/api_1.php', '/api_2.php', '/api_3.php' ];
var host = 'www.example.com';
var APIs = APIs.map(function (api) {
  return 'http://' + host + api;
});

function callAPIs ( host, APIs ) {
  var API = APIs.shift();
  request(API, function(err, res, body) {
    if( APIs.length ) {
      callAPIs ( host, APIs );
    }
  });
}

callAPIs( host, APIs );

편집 : 요청 / 비동기 버전

var request = require('request');
var async = require('async');
var APIs = [ '/api_1.php', '/api_2.php', '/api_3.php' ];
var host = 'www.example.com';
var APIs = APIs.map(function (api) {
  return 'http://' + host + api;
});

async.eachSeries(function (API, cb) {
  request(API, function (err, res, body) {
    cb(err);
  });
}, function (err) {
  //called when all done, or error occurs
});


답변

이 문제에 대한 해결책은 끝이없는 것 같습니다. 여기에 하나 더 있습니다. 🙂

// do it once.
sync(fs, 'readFile')

// now use it anywhere in both sync or async ways.
var data = fs.readFile(__filename, 'utf8')

http://alexeypetrushin.github.com/synchronize


답변

또 다른 가능성은 완료된 작업을 추적하는 콜백을 설정하는 것입니다.

function onApiResults(requestId, response, results) {
    requestsCompleted |= requestId;

    switch(requestId) {
        case REQUEST_API1:
            ...
            [Call API2]
            break;
        case REQUEST_API2:
            ...
            [Call API3]
            break;
        case REQUEST_API3:
            ...
            break;
    }

    if(requestId == requestsNeeded)
        response.end();
}

그런 다음 각각에 ID를 할당하고 연결을 닫기 전에 완료해야하는 작업에 대한 요구 사항을 설정할 수 있습니다.

const var REQUEST_API1 = 0x01;
const var REQUEST_API2 = 0x02;
const var REQUEST_API3 = 0x03;
const var requestsNeeded = REQUEST_API1 | REQUEST_API2 | REQUEST_API3;

좋아요, 예쁘지 않습니다. 순차 호출을하는 또 다른 방법입니다. NodeJS가 가장 기본적인 동기 호출을 제공하지 않는 것은 유감입니다. 그러나 나는 비동기성에 대한 유혹이 무엇인지 이해합니다.