2013-04-29 96 views
4

我剛剛花了幾個小時閱讀所以回答如Meteor: Calling an asynchronous function inside a Meteor.method and returning the result如何從Meteor自己的回調中調用異步方法?

不幸的是,我仍然沒有設法用戶纖維,或期貨的事情。

我想做一些相當簡單的事情(我想!)。

創建用戶時,根據異步方法的結果向用戶對象添加變量。所以想象一下,如果我的異步方法在名爲BANK的第三方數據庫服務器上調用,可能需要幾秒鐘才能返回。

Accounts.onCreateUser(function(options,user){ 

var Fiber = Npm.require("fibers"); 

Fiber(function() { 
    BANK.getBalance(function(err, theBalance) { 

     if (err) return console.log(err); 

     _.extend(user,{ 
      balance: theBalance; 
     }); 

    }); 
}).run(); 

return user; 

});

因此,上述情況發生的是BANK方法被調用,但在返回時代碼已經移動並且_.extend從不被調用。

我試着把光纖內的回調稱爲事件,這隻會讓事情變得更糟:它永遠不會返回用戶。它的確如此,但是3秒太晚了,所以下游的一切都在救助。

謝謝你的幫助!

+1

迎接那些沒有解釋就低估了我的問題的人...可能是一個PHP粉絲。 – 2013-04-29 06:41:28

+0

lmao @Stephan Tual – 2016-02-05 12:23:20

回答

5

回答我自己的問題有望在未來幫助一些人。這是基於Avital Oliver和David Glasser對Mike Bannister的meteor-async.md的出色建議。你可以在這裏閱讀:https://gist.github.com/possibilities/3443021

Accounts.onCreateUser(function(options,user){ 
    _.extend(user,{ 
     balance: getBalance(), 
    }); 
    return user; 
}); 


function getBalance() { 
    var Future = Npm.require("fibers/future"); 
    var fut = new Future(); 
    BANK.getBalance(function(err, bal) { 
    if (err) return console.log(err); 
    fut.return(bal); 
    }); 
    return fut.wait(); 
} 

我相信有一個更好的方式來處理這個問題,這是直接由故宮封裝本身內包裹BANK API中證期貨,按照本例(從阿維塔爾奧利弗) :https://github.com/avital/meteor-xml2js-npm-demo/blob/master/xml2js-demo.js

我希望它有幫助!

+1

那麼,發生錯誤時會發生什麼?當這個未來不再回來時會發生什麼?有沒有辦法拒絕未來? – Sinetheta 2013-07-21 22:23:49

+1

是的,如果有人可以評論優雅的錯誤處理,這將是偉大的!現在,因爲你不能在將來拋出Meteor.throw(),我必須在調用它的函數中進行錯誤處理......真的很醜陋:( – 2013-07-21 22:32:15

0

方法調用使用同步樣式(見「同步調用」這裏http://docs.meteor.com/#meteor_call)在服務器端,這是在這個創建用戶方法運行 - 你應該能夠做到像

Accounts.onCreateUser(function(options, user) { 
    user.balance = Meteor.call('getBankBalance', params); 
    return user; 
}); 
+0

嗨Nate,可悲的是這個通話方式對我來說並不奏效,因爲流星。調用('getBalance',param)只會調用服務器API調用的現有實現,它是異步的並需要幾秒鐘才能返回等。無論如何,謝謝! – 2013-04-29 20:53:48

+0

實際上,如果我只是調用Meteor.call('BANK.getBalance'),就可以正確處理第一個調用,並且每個後續調用都會一次又一次返回相同的餘額。不知道爲什麼。 – 2013-04-29 23:59:29

0

非常感謝你的工作,這個解決方案更適合Meteor項目,因爲默認情況下安裝了Fibers模塊。 mrt添加npm也有一個方法 - > Meteor.sync。對於任何項目的NodeJS有基於纖維的其它模塊,它的名字是纖維

參考:https://github.com/goodeggs/fibrous

1

使用this.unblock()在服務器端代碼。

來自Meteor 1.0文檔:「允許來自該客戶端的後續方法開始在新光纖中運行。在服務器上,來自給定客戶端的方法一次只運行一個,客戶端的第N + 1次調用不會直到第N次調用返回,但是,你可以通過調用this.unblock來改變它,這將允許第N + 1次調用開始在新光纖中運行。

Meteor.methods({checkTwitter: function (userId) { 
check(userId, String); 
this.unblock(); 
try { 
    var result = HTTP.call("GET", "http://api.twitter.com/xyz", 
         {params: {user: userId}}); 
    return true; 
} catch (e) { 
    // Got a network error, time-out or HTTP error in the 400 or 500 range. 
return false; 
} 

}});