Meteor 和 Fibers/bindEnvironment() 是怎么回事? [英] What's going on with Meteor and Fibers/bindEnvironment()?

查看:16
本文介绍了Meteor 和 Fibers/bindEnvironment() 是怎么回事?的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

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

I am having difficulty using Fibers/Meteor.bindEnvironment(). I tried to have code updating and inserting to a collection if the collection starts empty. This is all supposed to be running server-side on startup.

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

我第一次写这篇文章时遇到错误,我需要将回调包装在 Fiber() 块中,然后在 IRC 上的讨论中,有人建议尝试使用 Meteor.bindEnvironment() 代替,因为那应该将它放在 Fiber() 块中.这不起作用(我看到的唯一输出是 inserting...,这意味着 bindEnvironment() 没有抛出错误,但它也没有运行内部的任何代码堵塞).然后我到了这个.我现在的错误是:错误:Meteor 代码必须始终在 Fiber 中运行.尝试使用 Meteor.bindEnvironment 包装传递给非 Meteor 库的回调.

My first time writing this, I got errors that I needed to wrap my callbacks in a Fiber() block, then on discussion on IRC someone recommending trying Meteor.bindEnvironment() instead, since that should be putting it in a Fiber. That didn't work (the only output I saw was inserting..., meaning that bindEnvironment() didn't throw an error, but it also doesn't run any of the code inside of the block). Then I got to this. My error now is: 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++/每种带有线程的语言中的线程,但我不明白扩展到我的服务器端代码的含义是什么/为什么我的代码在尝试插入时抛出错误一个集合.谁能给我解释一下?

I am new to Node and don't completely understand the concept of Fibers. My understanding is that they're analogous to threads in C/C++/every language with threading, but I don't understand what the implications extending to my server-side code are/why my code is throwing an error when trying to insert to a collection. Can anyone explain this to me?

谢谢.

推荐答案

您对 bindEnvironment 的使用有点不正确.因为它被使用的地方已经在纤程中,而从 Knox 客户端发出的回调不再在纤程中.

You're using bindEnvironment slightly incorrectly. Because where its being used is already in a fiber and the callback that comes off the Knox client isn't in a fiber anymore.

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

There are two use cases of bindEnvironment (that i can think of, there could be more!):

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

  • You have a global variable that has to be altered but you don't want it to affect other user's sessions

您正在使用第三方 api/npm 模块管理回调(看起来确实如此)

You are managing a callback using a third party api/npm module (which looks to be the case)

Meteor.bindEnvironment 创建一个新的 Fiber 并将当前 Fiber 的变量和环境复制到新的 Fiber.当您使用 nom 模块的方法回调时,您需要这样做.

Meteor.bindEnvironment creates a new Fiber and copies the current Fiber's variables and environment to the new Fiber. The point you need this is when you use your nom module's method callback.

幸运的是,有一种替代方法可以处理等待您的回调,并将回调绑定到名为 Meteor.wrapAsync 的光纤中.

Luckily there is an alternative that takes care of the callback waiting for you and binds the callback in a fiber called Meteor.wrapAsync.

所以你可以这样做:

您的启动函数已经有一个 Fiber 并且没有回调,因此您不需要在这里使用 bindEnvironment.

Your startup function already has a fiber and no callback so you don't need bindEnvironment here.

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

你的插入记录功能(使用 wrapAsync)所以你不需要回调

And your insert records function (using wrapAsync) so you don't need a 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 中只有一个线程.

A couple of things to keep in mind. Fibers aren't like threads. There is only a single thread in NodeJS.

Fiber 更像是可以同时运行但不会相互阻塞的事件,如果存在等待类型的场景(例如从 Internet 下载文件).

Fibers are more like events that can run at the same time but without blocking each other if there is a waiting type scenario (e.g downloading a file from the internet).

这样您就可以拥有同步代码,而不会阻止其他用户的事件.它们轮流运行,但仍运行在单个线程中.所以这就是 Meteor 在服务器端有同步代码的方式,它可以等待东西,而其他用户不会被这个阻塞,可以做一些事情,因为他们的代码在不同的光纤中运行.

So you can have synchronous code and not block the other user's events. They take turns to run but still run in a single thread. So this is how Meteor has synchronous code on the server side, that can wait for stuff, yet other user's won't be blocked by this and can do stuff because their code runs in a different fiber.

Chris Mather 在 http://eventedmind.com

Chris Mather has a couple of good articles on this on http://eventedmind.com

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

Meteor.wrapAsync takes in the method you give it as the first parameter and runs it in the current fiber.

它还给它附加了一个回调(它假设该方法采用最后一个参数,该参数具有一个回调,其中第一个参数是错误,第二个参数是结果,例如 function(err,result).

It also attaches a callback to it (it assumes the method takes a last param that has a callback where the first param is an error and the second the result such as function(err,result).

回调与 Meteor.bindEnvironment 绑定并阻塞当前 Fiber 直到回调被触发.一旦回调触发,它就会返回 result 或抛出 err.

The callback is bound with Meteor.bindEnvironment and blocks the current Fiber until the callback is fired. As soon as the callback fires it returns the result or throws the err.

因此将异步代码转换为同步代码非常方便,因为您可以在下一行使用方法的结果,而不是使用回调和嵌套更深的函数.它还为您处理了 bindEnvironment,因此您不必担心失去光纤的作用域.

So it's very handy for converting asynchronous code into synchronous code since you can use the result of the method on the next line instead of using a callback and nesting deeper functions. It also takes care of the bindEnvironment for you so you don't have to worry about losing your fiber's scope.

更新 Meteor._wrapAsync 现在是 Meteor.wrapAsync已记录.

这篇关于Meteor 和 Fibers/bindEnvironment() 是怎么回事?的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆