meteor和光纤/ bindEnvironment()发生了什么?

我有困难使用Fibers / Meteor.bindEnvironment()。 如果集合开始为空,我试图进行代码更新并插入到集合中。 这一切都应该在启动时运行在服务器端。

function insertRecords() { console.log("inserting..."); var client = Knox.createClient({ key: apikey, secret: secret, bucket: 'profile-testing' }); console.log("created client"); client.list({ prefix: 'projects' }, function(err, data) { if (err) { console.log("Error in insertRecords"); } for (var i = 0; i < data.Contents.length; i++) { console.log(data.Contents[i].Key); if (data.Contents[i].Key.split('/').pop() == "") { Projects.insert({ name: data.Contents[i].Key, contents: [] }); } else if (data.Contents[i].Key.split('.').pop() == "jpg") { Projects.update( { name: data.Contents[i].Key.substr(0, data.Contents[i].Key.lastIndexOf('.')) }, { $push: {contents: data.Contents[i].Key}} ); } else { console.log(data.Contents[i].Key.split('.').pop()); } } }); } if (Meteor.isServer) { Meteor.startup(function () { if (Projects.find().count() === 0) { boundInsert = Meteor.bindEnvironment(insertRecords, function(err) { if (err) { console.log("error binding?"); console.log(err); } }); boundInsert(); } }); } 

我第一次写这篇文章的时候,我得到了一些错误,我需要将我的callback包装在一个Fiber()块中,然后讨论IRC,有人build议尝试使用Meteor.bindEnvironment(),因为这应该放在Fiber中。 这没有用(我看到的唯一的输出是inserting... ,这意味着bindEnvironment()没有抛出一个错误,但它也不会运行块内的任何代码)。 然后我做到了。 我现在的错误是: Error: Meteor code must always run within a Fiber. Try wrapping callbacks that you pass to non-Meteor libraries with Meteor.bindEnvironment. Error: Meteor code must always run within a Fiber. Try wrapping callbacks that you pass to non-Meteor libraries with Meteor.bindEnvironment.

我是Node新手,并没有完全理解Fibers的概念。 我的理解是,他们类似于线程在C / C + + /每种语言与线程,但我不明白是什么扩展到我的服务器端代码是/为什么我的代码是试图插入时发生错误一个集合。 任何人都可以向我解释这个?

谢谢。

你正在稍微不正确地使用bindEnvironment。 因为它被使用的地方已经在光纤中,Knox客户端的callback不再是光纤了。

有两个bindEnvironment的使用情况(我能想到,可能还有更多!):

  • 你有一个全局variables必须被改变,但你不希望它影响其他用户的会话

  • 你正在使用第三方api / npm模块pipe理callback(看起来是这样)

Meteor.bindEnvironment创build一个新的光纤,并将当前光纤的variables和环境复制到新的光纤。 你需要的是当你使用你的nom模块的方法callback。

幸运的是,还有一个替代scheme可以处理等待您的callback,并将这个callback绑定到名为Meteor.wrapAsync的光纤上。

所以你可以这样做:

你的启动函数已经有一个光纤,没有callback,所以你不需要bindEnvironment这里。

 Meteor.startup(function () { if (Projects.find().count() === 0) { insertRecords(); } }); 

而你的插入loggingfunction(使用wrapAsync),所以你不需要callback

 function insertRecords() { console.log("inserting..."); var client = Knox.createClient({ key: apikey, secret: secret, bucket: 'profile-testing' }); client.listSync = Meteor.wrapAsync(client.list.bind(client)); console.log("created client"); try { var data = client.listSync({ prefix: 'projects' }); } catch(e) { console.log(e); } if(!data) return; for (var i = 1; i < data.Contents.length; i++) { console.log(data.Contents[i].Key); if (data.Contents[i].Key.split('/').pop() == "") { Projects.insert({ name: data.Contents[i].Key, contents: [] }); } else if (data.Contents[i].Key.split('.').pop() == "jpg") { Projects.update( { name: data.Contents[i].Key.substr(0, data.Contents[i].Key.lastIndexOf('.')) }, { $push: {contents: data.Contents[i].Key}} ); } else { console.log(data.Contents[i].Key.split('.').pop()); } } }); 

有几件事要记住。 纤维不像线程。 NodeJS中只有一个线程。

纤维更像是可以同时运行的事件,但是如果存在等待types的情况(例如从互联网下载文件),则不会彼此阻塞。

所以你可以有同步代码,而不是阻止其他用户的事件。 他们轮stream运行,但仍然运行在一个单一的线程。 所以这就是Meteor在服务器端的同步代码,可以等待的东西,但其他用户不会被阻止,可以做的东西,因为他们的代码运行在不同的光纤。

克里斯·马瑟(Chris Mather)在http://eventedmind.com上有一些关于这方面的好文&#x7AE0;

Meteor.wrapAsync是做什么的?

Meteor.wrapAsync接受你给它的方法作为第一个参数,并在当前光纤中运行它。

它还附加了一个callbackfunction(err,result)它假定方法最后一个参数有一个callbackfunction(err,result) ,第一个参数是错误的,第二个function(err,result)的结果是function(err,result)

callback与Meteor.bindEnvironment绑定,并阻止当前的光纤直到callback被触发。 一旦callback触发它返回result或抛出err

所以将asynchronous代码转换为同步代码非常方便,因为您可以在下一行使用方法的结果,而不是使用callback和嵌套深层function。 它也为您的照顾环境,所以你不必担心失去光纤的范围。

更新 Meteor._wrapAsync现在是Meteor.wrapAsync和logging 。