2013-05-31 15 views
33

Tôi đang sử dụng mô-đun thể hiện để tạo API Restful trong Node.JS. Trong dịch vụ của tôi, tôi đang thực hiện các yêu cầu http bổ sung cho các Điểm cuối bên ngoài (phía máy chủ) và tôi cần trả lại dữ liệu từ các yêu cầu http đó đến cơ quan yêu cầu dịch vụ web của tôi.Node.JS Đợi gọi lại dịch vụ REST yêu cầu HTTP

Tôi đã xác nhận rằng nếu tôi sử dụng console.log trên tất cả các hành động mà Dịch vụ web đang tiến hành, tôi sẽ nhận được dữ liệu tôi cần. Tuy nhiên, khi tôi cố gắng trả lại những giá trị đó cho dịch vụ họ quay trở lại Null. Tôi biết rằng điều này là do async và gọi lại không phải chờ đợi cho yêu cầu http để kết thúc.

Có cách nào để thực hiện công việc này không?

+0

Bạn cần chấp nhận gọi lại. – SLaks

Trả lời

41

Cách thông thường là sử dụng mô-đun async.

npm install async 

Mô-đun async có nguyên tắc xử lý các dạng sự kiện không đồng bộ khác nhau.

Trong trường hợp của bạn, cuộc gọi async#parallel sẽ cho phép bạn thực hiện yêu cầu cho tất cả các API bên ngoài cùng một lúc và sau đó kết hợp các kết quả để trả lại cho người yêu cầu của bạn.

Vì bạn đang thực hiện các yêu cầu http bên ngoài, có thể bạn sẽ tìm thấy mô-đun request hữu ích.

npm install request 

Sử dụng requestasync#parallel handler tuyến đường của bạn sẽ giống như thế này ...

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

Bạn cũng có thể đọc về các phương thức callback trình tự khác here.

+0

Điều này có vẻ đầy hứa hẹn. Làm thế nào tôi sẽ gọi điều này? – Rob

+0

đã tìm ra. Cảm ơn! – Rob

+0

Chà. Bạn chỉ cần tiết kiệm cho tôi số giờ tìm kiếm –

17

Node.js là tất cả về các cuộc gọi lại. Trừ khi cuộc gọi API là đồng bộ (hiếm và không nên thực hiện), bạn không bao giờ trả lại giá trị từ các cuộc gọi đó, nhưng gọi lại với kết quả từ trong phương thức gọi lại hoặc gọi phương thức thể hiện res.send

Thư viện tuyệt vời cho gọi các yêu cầu web là request.js

Hãy lấy ví dụ thực sự đơn giản gọi google. Sử dụng res.send, mã express.js của bạn có thể trông giống như:

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

Ngoài ra, bạn có thể vượt qua một callback với phương pháp dùng để gọi yêu cầu web, và gọi callback mà từ bên trong phương pháp đó:

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

ví dụ câu trả lời của khác sử dụng wait.for:

Ví dụ từ từ trả lời của Daniel (không đồng bộ), nhưng sử dụng 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); 
      }); 
}