4

我刚刚花了几个小时阅读 SO 的答案,例如Meteor: Calling an asynchronous function inside a Meteor.method and return the result

不幸的是,我仍然没有设法使用光纤或期货。

我正在尝试做一些相当简单的事情(我认为!)。

创建用户时,根据异步方法的结果向用户对象添加一个变量。所以想象一下,如果你会在名为 BANK 的第 3 方数据库服务器上调用我的异步方法,这可能需要几秒钟才能返回。

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。

我尝试将返回调用放在 Fiber 中,这只会让事情变得更糟:它永远不会返回用户。确实如此,但为时已晚 3 秒,所以到那时下游的一切都在救助。

感谢您的任何帮助!

4

4 回答 4

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 包装在 npm 包本身的 Futures 中,根据这个例子(来自 Avital Oliver):https ://github.com/avital/meteor-xml2js -npm-demo/blob/master/xml2js-demo.js

我希望它有帮助!

于 2013-04-29T20:52:11.660 回答
1

在服务器端代码上使用 this.unblock()。

来自 Meteor 1.0 文档:“允许来自该客户端的后续方法开始在新光纤中运行。在服务器上,来自给定客户端的方法一次运行一个。来自客户端的第 N+1 次调用将在第 N 次之前开始“

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

}});

于 2014-12-21T01:02:55.177 回答
0

方法调用在服务器端使用同步样式(请参阅此处的“同步调用” http://docs.meteor.com/#meteor_call),这是创建用户方法运行的地方 - 您应该能够执行类似的操作

Accounts.onCreateUser(function(options, user) {
  user.balance = Meteor.call('getBankBalance', params);
  return user;
});
于 2013-04-29T14:04:53.567 回答
0

非常感谢你,这个解决方案更适合 Meteor 项目,因为默认安装了 Fibers 模块。mrt add npm 也有一个方法 -> Meteor.sync 。对于任何 nodeJS 项目,都有一个基于 Fibers 的模块,它的名字是 Fibrous

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

于 2013-12-03T19:19:44.860 回答