Meteor wrapasync save Twitter REST response to Mongo collection giving an error "Error: Meteor code must always run within a Fiber."

Meteor wrapasync save Twitter REST response to Mongo collection giving an error "Error: Meteor code must always run within a Fiber."

我正在尝试使用 Twitter REST API GET followers/ids 并使用 Mongo collection 插入方法

将其保存到 Mongo

里面的代码/server/server.js:

Meteor.startup(function () {
    // code to run on server at startup

    TwitterFollowersIDsCollecions = new Mongo.Collection("twitterFollowersIDs");

    var Twit = Meteor.npmRequire('twit');
    var T = new Twit({
        consumer_key:         '###',
        consumer_secret:      '###',
        access_token:         '###',
        access_token_secret:  '###'
    });

    var getTwitterFollowersIDsAsync = function (screenname, cb) {
        T.get('followers/ids', { screen_name: screenname }, function (err, data, response) {
                console.log(data);
                var vids = data.ids;
                for(var i in vids) {
                    TwitterFollowersIDsCollecions.insert({
                        twitterFollowerID:vids[i]
                    });
                }
            }
        );
    };

    Meteor.methods({
        getTwitterFollowersIDsCollectionsClient : function (screenname){
            var getTwitterFollowersIDsNow = Meteor.wrapAsync(getTwitterFollowersIDsAsync);
            var result = getTwitterFollowersIDsNow('meteorjs');
            console.log(result);
            return result;
        }
    });

});

服务器控制台错误:

Error: Meteor code must always run within a Fiber. 
Try wrapping callbacks that you pass to non-Meteor libraries with Meteor.bindEnvironment.

Objective是将twitter关注者保存到Mongocollection.

Meteor 1.1.0.2 版

流星包:

通过 meteorhacks:npm 在 Meteor 内部使用的 npm 模块:"twit": "1.1.20"(在 packages.json 中添加)

**更新第二次尝试**

Meteor.startup(function () {

  // code to run on server at startup

  TwitterFollowersIDsCollecions = new Mongo.Collection("twitterFollowersIDs");

  var Twit = Meteor.npmRequire('twit');

  var T = new Twit({
        consumer_key:         '###',
        consumer_secret:      '###',
        access_token:         '###',
        access_token_secret:  '###'
    });

  Meteor.methods({

    // this is the server method called from the client

    getTwitterFollowersIDsCollectionsClient : function (){
      setTimeout(function(){
        Meteor.call('getTwitterFollowersIDsNow', 'meteorjs');
      },10);
      return;
    },

    getTwitterFollowersIDsNow : function (screenname) {
      T.get('followers/ids', { screen_name: screenname }, function (err, data, response) {
        console.log(data);
      });
    }

  });

});

然后我从浏览器控制台调用以下代码:

Meteor.call('getTwitterFollowersIDsCollectionsClient');

服务器因同样的错误而崩溃:

Error: Meteor code must always run within a Fiber. Try wrapping callbacks     that you pass to non-Meteor libraries with Meteor.bindEnvironment.

更新:

getTwitterFollowersIDsCollectionsClient : function (screenname){
  Meteor.setTimeout(function(screenname){
    T.get('followers/ids', { screen_name: screenname }, Meteor.bindEnvironment(function (err, data, response) {
    console.log("from getTwitterFollowersIDsCollectionsClient : "+data.ids);

    var vids = data.ids;
    for(var i in vids)
      {
        TwitterFollowersIDsCollecions.insert({
          twitterFollowerID:vids[i]
        });
      }

    return data;
  }));

  },10);
  return;
}

已将 Meteor.bindEnvironment 添加到 T.get 回调方法。此代码有效,我能够将关注者 ID 保存到 mongo collection

您的代码有点混乱。看起来您正在尝试异步执行 Web 服务调用,但仍然 return 立即得到结果(这是行不通的)。

首先,您可能不需要包装函数来获取异步块中的关注者。

如果您希望服务器方法在调用后立即向客户端 return 发送某些内容,我会使用 Meteor.setTimeout(参见 What's the point of Meteor.setTimeout() vs just setTimeout()?)块并调用另一个获取方法:

Meteor.methods({

    // this is the server method called from the client
    getTwitterFollowersIDsCollectionsClient : function (screenname){
        Meteor.setTimeout(function() { 
          Meteor.call('getTwitterFollowersIDsNow', 'meteorjs');
        }, 10);
        return;
    },

    getTwitterFollowersIDsNow : function (screenname) {
        T.get('followers/ids', { screen_name: screenname }, function (err, data, response) {
            console.log(data);
            var vids = data.ids;
            for(var i in vids) {
                TwitterFollowersIDsCollecions.insert({
                    twitterFollowerID:vids[i]
                });
            }
        }
    }
});

理想情况下,您可以使用模板助手从 collection 中检索您的关注者。由于这些助手是反应性的,您可以只从客户端调用服务器方法,让 Meteor 的反应性解决您通过助手(re-executed/re-rendering 模板)return关注者的问题关于数据更改)。

很高兴你让它工作了,但我试过这个,Meteor 提供了另一种超级简单的方法:wrapAsync。至少,一旦我想通了,这很容易!这是我用 -

结束的服务器代码
var T = new TwitMaker({
    consumer_key:         '...'
  , consumer_secret:      '...'
  , access_token:         '...'
  , access_token_secret:  '...'
})

var wrapGet = Meteor.wrapAsync(T.get, T);

Meteor.methods({

  getTwitImg: function(target) {
    data = wrapGet('users/show', {screen_name: target});
    if (data) {
      img_url = data['profile_image_url'];
      US.update({twitter: target}, {$set: {'targetImg': img_url}});
      return img_url;
    }
  }

});

有关客户端和模板代码,请参阅此要点:https://gist.github.com/DanAncona/a09ce375e48bfa8efeca

尝试调用:

var wrappedInsert = Meteor.bindEnvironment(function(tweet) {
TweetsCollection.insert(tweet);},
"Failed to insert tweet into Posts collection.");

来自 api 回调内部

getTwitterFollowersIDsNow : function (screenname) {
  T.get('followers/ids', { screen_name: screenname }, function (err, data, response) {
    for(var i in data)
    {
     wrappedInsert(data[i]);
    }     
  });
}