当前位置: 首页 > 面试题库 >

流星和Fibers / bindEnvironment()怎么了?

孙和安
2023-03-14
问题内容

我在使用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();
    }
  });
}

我第一次编写此文件时,遇到了一些错误,需要将回调包装在Fiber()块中,然后在IRC上讨论时,有人建议尝试使用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.

我是Node的新手,并不完全了解Fibers的概念。我的理解是,它们类似于使用线程的C / C ++
/每种语言中的线程,但是我不明白扩展到服务器端代码的含义是/为什么我的代码在尝试插入时会引发错误。集合。谁能向我解释一下?

谢谢。


问题答案:

您使用的bindEnvironment略有错误。因为它的使用位置已经在光纤中,而离开Knox客户端的回调不再在光纤中。

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

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

  • 您正在使用第三方api / npm模块管理回调(情况似乎如此)

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

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

因此,您可以这样做:

您的启动函数已经有一个光纤并且没有回调,因此您在这里不需要bindEnvironment。

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

而且您的插入记录功能(使用wrapAsync)使您不需要回调

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中只有一个线程。

光纤更像是可以同时运行的事件,但如果存在等待类型的情况(例如,从Internet下载文件),则不会互相阻塞。

因此,您可以拥有同步代码,而不会阻止其他用户的事件。它们轮流运行,但仍在单个线程中运行。因此,这就是Meteor在服务器端具有同步代码的方式,可以等待内容,但是其他用户不会因此而受阻,并且可以执行内容,因为他们的代码在不同的光纤上运行。

克里斯·马瑟(Chris
Mather)在http://eventedmind.com上有几篇很好的文章

Meteor.wrapAsync是做什么的?

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

它还会附加一个回调(假定该方法采用的最后一个参数具有回调,其中第一个参数是错误,第二个参数是function(err,result)

回调与绑定Meteor.bindEnvironment并阻塞当前Fiber,直到触发回调为止。回调触发后立即返回result或引发err

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

*Meteor._wrapAsync现在已
*更新
Meteor.wrapAsync并记录在案。



 类似资料:
  • 问题内容: 我正在寻找如何在Meteor Up Docker上安装Graphicsmagick。 我找到了这个解决方案docker中的Accessbinaries,但是我无法工作,我应该将这些行放在哪里? 那是我的: 问题答案: 每次您重新启动容器时都要重新安装graphicsmagick软件包,这看起来像是我不想做的黑客。 如果您已经在修改启动脚本,则不妨使用Dockerfile: 然后修改模板

  • 本文向大家介绍meteor 检查流星工具和流星项目的版本,包括了meteor 检查流星工具和流星项目的版本的使用技巧和注意事项,需要的朋友参考一下 示例 流星工具 要检查Meteor工具的安装版本,只需在任何Meteor项目之外运行以下命令: 要获取所有官方(推荐)Meteor版本的列表,请运行: 流星项目 如果要检查Meteor的项目版本,还可以在项目内执行以下命令: 或仅打印文件内容.mete

  • 我浏览了exoplayer的网站和文档以及Github页面,但我对其解释并不满意。 任何人都可以给我一个提示,你如何通过ExoPlayer播放一个http直播流视频? 提前道谢。

  • 从隐藏元素不再占用空间的意义上来说,在iOS中制作流畅布局的正确方法是什么? 我有一个表格视图,每个单元格中有一个定制的详细类型的视图,带有标题、副标题和一行额外信息: 额外信息最多可以是三对图标和一个带有值的标签。单元内所有视图的布局都是使用AutoLayout完成的,没有丢失或不明确的约束。 我想实现的是,当值为0时,图标和标签不会显示,右侧的视图会向左移动。 如果我只使用< code>set

  • 我有一个字符串a的列表,并试图找到a的所有元素a按照某种规则与a的另一个元素b匹配,然后创建一个,其中包含所有的a->所有匹配的b。 详细内容: 对于a中的每个a,使用谓词P将其与a中的每个b进行比较。 如果P(a,b)匹配,则从a和b生成一对(x,y)。 将所有对按x分组,并以映射形式返回。 这种方法的问题是,我首先需要构造一个庞大的对列表,如果我的数据集只有几百万字,那么它可能会耗尽内存。

  • 问题内容: 更新 此解决方案描述了如何有效使用Meteor中的新Npm系统。 如果可以使用1.3,请检查http://guide.meteor.com/using-packages.html#installing-npm。 例如,要使用moment.js: 然后在您的代码中: 在Meteor中使用NPM软件包的当前方法是什么? 关于此有几个问题,尤其是[这个问题,但是解决方案似乎已经过时:引擎分支