2014-09-19 17 views
9

Vì vậy, tôi có một phương thức Meteor được yêu cầu báo cho máy chủ gửi nhiều yêu cầu API tới API của bên thứ ba và sau đó kết hợp các kết quả của các truy vấn này vào một mảng, được trả lại cho máy khách.sao băng - Đồng bộ hóa nhiều truy vấn không đồng bộ trước khi trở về?

Tuy nhiên, tôi dường như không thể tìm cách để máy chủ đợi cho đến khi tất cả truy vấn API đã hoàn tất trước khi trả lại kết quả.

Phiên bản đồng bộ của mã này, mà chỉ fetches các cuộc gọi dữ liệu API khác, đi như thế này:

Meteor.methods({ 
    fetchData: function(APILinks) { 
     var data = []; 
     APILinks.forEach(function(APILink) { 
      var items = HTTP.get(APILink).content.items; 
      items.forEach(function (item) { 
       data.push(item); 
      }); 
     }); 
     return items; 
    } 
}); 

đang đồng bộ này hoạt động. Tuy nhiên, tôi đã không thể tìm thấy một cách tốt để làm cho các yêu cầu API không đồng bộ. Gần nhất tôi có thể nhận được một giải pháp là xác định lại phương thức để trả về kết quả của chỉ một yêu cầu API, và sau đó có vòng lặp phía máy khách thông qua mỗi liên kết API và gọi phương thức cho mỗi một trong số chúng. Tuy nhiên, có cách nào để bọc tất cả các yêu cầu này thành một phương thức tốt đẹp chỉ trả lại khi tất cả các yêu cầu API hoàn tất không?

Trả lời

12

Bạn phải sử dụng phiên bản không đồng bộ HTTP.get và thu thập kết quả bằng cách sử dụng Future s.

Tôi đã tạo một ví dụ đơn giản sử dụng setTimeout s để mô phỏng các yêu cầu HTTP để bạn hiểu nguyên tắc, tôi khuyên bạn nên bắt đầu từ mã này và thay thế giả setTimeout bằng yêu cầu nhận HTTP của bạn.

Ví dụ này là một phương thức máy chủ test nhận một số nhiệm vụ (n) làm tham số, sau đó khởi chạy các tác vụ mà mỗi tính toán hình vuông chỉ mục của chúng trong chỉ số giây.

// we use fibers which is a dependency of Meteor anyway 
var Future = Npm.require("fibers/future"); 

Meteor.methods({ 
    test: function(n) { 
     // build a range of tasks from 0 to n-1 
     var range = _.range(n); 
     // iterate sequentially over the range to launch tasks 
     var futures = _.map(range, function(index) { 
      var future = new Future(); 
      console.log("launching task", index); 
      // simulate an asynchronous HTTP request using a setTimeout 
      Meteor.setTimeout(function() { 
       // sometime in the future, return the square of the task index 
       future.return(index * index); 
      }, index * 1000); 
      // accumulate asynchronously parallel tasks 
      return future; 
     }); 
     // iterate sequentially over the tasks to resolve them 
     var results = _.map(futures, function(future, index) { 
      // waiting until the future has return 
      var result = future.wait(); 
      console.log("result from task", index, "is", result); 
      // accumulate results 
      return result; 
     }); 
     // 
     console.log(results); 
     return results; 
    } 
}); 

Nhập > Meteor.call("test",3,function(error,result){console.log(result);}); trong bảng điều khiển trình duyệt của bạn. Điều này sẽ xuất ra [0,1,4] sau 3 giây.

Trong giao diện điều khiển máy chủ của bạn, điều này sẽ đầu ra:

// immediately : 
launching task 0 
launching task 1 
launching task 2 
// after 1 second : 
result from task 0 is 0 
// after 2 seconds : 
result from task 1 is 1 
// after 3 seconds : 
result from task 2 is 4 
[ 0, 1, 4 ] 

Phiên bản không đồng bộ HTTP.get được nêu chi tiết trong tài liệu Meteor:

http://docs.meteor.com/#http_call

Nếu bạn muốn hiểu rõ hơn về toàn bộ Future khái niệm, tham khảo các tài liệu sợi:

https://github.com/laverdet/node-fibers

+0

Meteor có một abstracción mát mẻ của tương lai: Meteor._wrapAsync, chevk nó ra để tránh các boilerplate –

+4

'Meteor.wrapAsync' là hữu ích khi bạn muốn chuyển các nhiệm vụ không đồng bộ vào các cuộc gọi đồng bộ liên tục thủ tục, nhưng nó sẽ không giúp ở đây vì những gì chúng tôi muốn đạt được là tung ra đồng thời một số nhiệm vụ không đồng bộ mà chúng tôi muốn thực hiện song song. Thêm vào đó sẽ không có điểm trong việc sử dụng 'Meteor.wrapAsync' để bọc' HTTP.get' vì nó đã phơi bày một phiên bản đồng bộ có sẵn khi bạn không chuyển bất kỳ callback nào làm đối số. – saimeunt

Các vấn đề liên quan