这是来源Meteor.wrapAsync https://github.com/meteor/meteor/blob/50e6d3143db8fc6e1fc3fb74da74b40c8dc7f3a4/packages/meteor/helpers.js#L90和来源superget.get https://github.com/visionmedia/superagent/blob/b36fd692139cf366486d45783ede45a4c90c4764/lib/client.js#L982
Meteor.wrapAsync
基本上是一个薄薄的包装纸Meteor.bindEnviroment https://github.com/meteor/meteor/blob/556c0e28e94b9351cbf0b28e80a71a4e35f1362a/packages/meteor/dynamics_nodejs.js#L84。它提供了一个等待的绑定函数Fiber
.
superget.get
最终尝试调用传递给它的回调函数Request.prototype.callback https://github.com/visionmedia/superagent/blob/b36fd692139cf366486d45783ede45a4c90c4764/lib/client.js#L814
这里有趣的是Meteor.bindEnvironment
采取Fibers.resolver https://github.com/laverdet/node-fibers/blob/master/future.js#L309函数(需要两个论点),并将其包装在一个函数中,该函数接受没有参数.
So when Request.prototype.callback
试图看看fn.length
看看是否应该用(err, res)
或发送错误emit
...它执行后者..
为了使其工作,我们需要短路Request.prototype.callback
并让它认为没有参数的函数可以调用为fn(err, res)
superget.Request.prototype.callback = function(err, res){
var fn = this._callback;
if (2 == fn.length || 0 == fn.length) return fn(err, res);
if (err) return this.emit('error', err);
fn(res);
};
或者,您可以编写自己的Meteor.wrapAsync
它提供了具有正确函数长度的回调。例如:
function wrapAsync(fn, context) {
//XXX Shortened version of wrapAsync. Only works on server, doesn't allow for callback to be passed.
return function (/* arguments */) {
var self = context || this;
var newArgs = _.toArray(arguments);
var fut = new Future();
var callback = Meteor.bindEnvironment(fut.resolver());
newArgs.push(function(err, res){
return callback.apply(this, arguments);
});
fn.apply(self, newArgs);
return fut.wait()
};
}