Meteor - 使用 Meteor.wrapAsync() 包装 NPM

2024-05-09

我正在尝试使用 Meteor.wrapAsync 包装超级代理 NPM,一切正常,直到下面代码的最后一行,这导致我的流星应用程序崩溃。

var superagent = Meteor.npmRequire('superagent');

// Example of how superagent works
superagent.get('http://127.0.0.1:8080/json/', function(result){
    console.log(result); // Works, shows the result
});

// This appears to work too
var agentAsync = Meteor.wrapAsync(superagent.get);

// This crashes app
agentAsync('http://127.0.0.1:8080/json/');

我还尝试将上下文传递给wrapAsync(),这没有什么区别:

var agentAsync = Meteor.wrapAsync(superagent.get, superagent);

这是控制台输出:

W20141124-17:31:32.094(0)? (STDERR)           
W20141124-17:31:32.136(0)? (STDERR) /home/ciwolsey/.meteor/packages/meteor-tool/.1.0.35.1bjny7b++os.linux.x86_64+web.browser+web.cordova/meteor-tool-os.linux.x86_64/dev_bundle/lib/node_modules/fibers/future.js:206
W20141124-17:31:32.136(0)? (STDERR)                         throw(ex);
W20141124-17:31:32.137(0)? (STDERR)                               ^
W20141124-17:31:32.137(0)? (STDERR) [object Object]
W20141124-17:31:32.137(0)? (STDERR)     at Object.Future.wait (/home/ciwolsey/.meteor/packages/meteor-tool/.1.0.35.1bjny7b++os.linux.x86_64+web.browser+web.cordova/meteor-tool-os.linux.x86_64/dev_bundle/lib/node_modules/fibers/future.js:326:15)
W20141124-17:31:32.137(0)? (STDERR)     at packages/meteor/helpers.js:118
W20141124-17:31:32.137(0)? (STDERR)     at app/server/main.js:5:1
W20141124-17:31:32.137(0)? (STDERR)     at app/server/main.js:8:3
W20141124-17:31:32.137(0)? (STDERR)     at /home/ciwolsey/projects/hello/.meteor/local/build/programs/server/boot.js:168:10
W20141124-17:31:32.138(0)? (STDERR)     at Array.forEach (native)
W20141124-17:31:32.138(0)? (STDERR)     at Function._.each._.forEach (/home/ciwolsey/.meteor/packages/meteor-tool/.1.0.35.1bjny7b++os.linux.x86_64+web.browser+web.cordova/meteor-tool-os.linux.x86_64/dev_bundle/lib/node_modules/underscore/underscore.js:79:11)
W20141124-17:31:32.138(0)? (STDERR)     at /home/ciwolsey/projects/hello/.meteor/local/build/programs/server/boot.js:82:5
=> Exited with code: 8

这是来源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()
  };
}
本文内容由网友自发贡献,版权归原作者所有,本站不承担相应法律责任。如您发现有涉嫌抄袭侵权的内容,请联系:hwhale#tublm.com(使用前将#替换为@)

Meteor - 使用 Meteor.wrapAsync() 包装 NPM 的相关文章