2014-09-19 97 views
9

因此,我有一個Meteor方法,它應該告訴服務器向第三方API發送多個API請求,然後將這些查詢的結果合併到一個返回給客戶端的數組中。meteor - 在返回之前同步多個異步查詢?

但是,我似乎無法找到一種方法讓服務器等待所有API查詢完成後再返回結果。

代碼,接連剛剛獲取數據API調用的同步版本,是這樣的:

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

此同步代碼工作。但是,我一直無法找到一種使API請求異步的好方法。最接近我可以得到的解決方案是重新定義方法返回只有一個API請求的結果,然後讓客戶端循環通過每個API鏈接並調用每個API的方法。但是,是否有辦法將所有這些請求包裝爲一個很好的方法,只有在所有API請求都完成時纔會返回

回答

12

您必須使用異步版本HTTP.get並使用Future s收集結果。

我做了一個簡單的例子,使用setTimeout s來模擬HTTP請求,以便您理解原理,我建議您從此代碼開始,並用您的HTTP請求替換虛擬setTimeout

該示例是一個test服務器方法,它將多個任務(n)作爲參數,然後啓動n個任務,每個任務在索引秒內計算其索引的平方。

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

在您的瀏覽器控制檯中鍵入> Meteor.call("test",3,function(error,result){console.log(result);});。這將在3秒後輸出[0,1,4]

在服務器控制檯,這將輸出:

// 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 ] 

HTTP.get異步版本流星文檔詳細說明:

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

如果你想更好地瞭解整個Future概念,參考纖維文檔:

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

+0

流星有一個很酷的期貨定價:Meteor._wrapAsync,chevk它是爲了避免樣板 – 2014-09-20 01:03:47

+4

當你想把異步任務變成連續的程序同步調用時,Meteor.wrapAsync非常有用,但它不會幫助你,因爲我們想要實現的是同時啓動我們想要並行執行的幾個異步任務。另外,使用'Meteor.wrapAsync'來封裝'HTTP.get'是沒有意義的,因爲當你沒有將任何回調函數作爲參數傳遞時,它已經公開了一個可用的同步版本。 – saimeunt 2015-01-10 23:49:02