我使用纤维/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的讨论中,有人建议try Meteor.而是bindEnvironment(),因为这应该把它放在光纤中.这不起作用(我看到的唯一输出是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还不熟悉,不完全理解光纤的概念.我的理解是,它们类似于C/C++/每种语言中的线程,但我不明白扩展到服务器端代码的含义是什么/为什么我的代码在try 插入到集合时抛出错误.谁能给我解释一下吗?

非常感谢.

推荐答案

您使用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绑定并阻塞当前光纤,直到触发回调.一旦回调触发,它就会返回result或抛出err.

因此,将异步代码转换为同步代码非常方便,因为您可以在下一行使用该方法的结果,而不是使用回调和嵌套更深层次的函数.它还可以为您保护环境,这样您就不必担心失go 光纤的作用域.

Update Meteor._wrapAsync现在是Meteor.wrapAsyncdocumented.

Mongodb相关问答推荐

MongoDB获取所有文档谁的S子文档只包含一个特定值?

MongoDB:如何获取多个$indexOfArray值?

MongoDB:如何从数组中的所有对象中删除属性?

DTO 验证适用于 POST,但不适用于 PUT

Mongo,通过 Lookup 计算多个文档中数组中的项目

MongoDB 聚合 $match 阶段与条件查询

MongoDB 按日期时间字段查询 1h 间隔

Mongoose 返回包含属性内任何位置的值的所有文档

在 MongoDb 中查询小于 NOW 的日期时间值

用 BsonRepresentation(BsonType.ObjectId) vs BsonId vs ObjectId 在 C# 中装饰属性之间的区别

.NET 中的 Mongodb 单元测试

嵌套数组内的Mongodb增量值

具有简单密码认证的 MongoDB 副本集

单个模式数组中的多个模式引用 - mongoose

MongoDB - 聚合 - 获取数组中的唯一项

MongoDB限制内存

判断字段是否存在于数组的子文档中

mongoosefind()不返回结果

将 FilterDefinition 转换为可以在 mongo shell 中运行的常规 json mongo 查询

findOneAndUpdate 中的文档未更新