38

server/statusboard.jsに次のコードがあります。

var require = __meteor_bootstrap__.require,
    request = require("request")   


function getServices(services) {
  services = [];
  request('http://some-server/vshell/index.php?type=services&mode=json', function (error, response, body) {
    var resJSON = JSON.parse(body);
     _.each(resJSON, function(data) {
       var host = data["host_name"];
       var service = data["service_description"];
       var hardState = data["last_hard_state"];
       var currState = data["current_state"];
       services+={host: host, service: service, hardState: hardState, currState: currState};
       Services.insert({host: host, service: service, hardState: hardState, currState: currState});
    });
  });
}

Meteor.startup(function () {
  var services = [];
  getServices(services);
  console.log(services);
});

基本的には、JSONフィードからデータを取得し、それをコレクションにプッシュしようとします。

Meteorを起動すると、次の例外が発生します。

app/packages/livedata/livedata_server.js:781
      throw exception;
            ^
Error: Meteor code must always run within a Fiber
    at [object Object].withValue (app/packages/meteor/dynamics_nodejs.js:22:15)
    at [object Object].apply (app/packages/livedata/livedata_server.js:767:45)
    at [object Object].insert (app/packages/mongo-livedata/collection.js:199:21)
    at app/server/statusboard.js:15:16
    at Array.forEach (native)
    at Function.<anonymous> (app/packages/underscore/underscore.js:76:11)
    at Request._callback (app/server/statusboard.js:9:7)
    at Request.callback (/usr/local/meteor/lib/node_modules/request/main.js:108:22)
    at Request.<anonymous> (/usr/local/meteor/lib/node_modules/request/main.js:468:18)
    at Request.emit (events.js:67:17)
Exited with code: 1

そのエラーが何を意味するのかよくわかりません。誰かが何かアイデアを持っていますか、または別のアプローチを提案できますか?

4

3 に答える 3

48

関数をファイバーでラップするだけでは不十分な場合があり、予期しない動作が発生する可能性があります。

その理由は、ファイバーとともに、Meteorはファイバーに接続された一連の変数を必要とするためです。Meteorは、ファイバーに接続されたデータを動的スコープとして使用します。サードパーティのAPIで使用する最も簡単な方法は、を使用することMeteor.bindEnvironmentです。

T.post('someurl', Meteor.bindEnvironment(function (err, res) {
  // do stuff
  // can access Meteor.userId
  // still have MongoDB write fence
}, function () { console.log('Failed to bind environment'); }));

詳細を知りたい場合は、イベントマインドに関するこれらのビデオをご覧ください: https ://www.eventedmind.com/posts/meteor-dynamic-scoping-with-environment-variables https://www.eventedmind.com/posts/meteor- what-is-meteor-bindenvironment

于 2013-08-30T21:38:00.647 に答える
15

上記のように、それはコールバック内でコードを実行しているためです。

サーバー側で実行しているコードはすべて、ファイバー内に含まれている必要があります。

getServices関数を次のように変更してみてください。

function getServices(services) {
  Fiber(function() { 
    services = [];
    request('http://some-server/vshell/index.php?type=services&mode=json', function (error, response, body) {
      var resJSON = JSON.parse(body);
       _.each(resJSON, function(data) {
         var host = data["host_name"];
         var service = data["service_description"];
         var hardState = data["last_hard_state"];
         var currState = data["current_state"];
         services+={host: host, service: service, hardState: hardState, currState: currState};
         Services.insert({host: host, service: service, hardState: hardState, currState: currState});
      });
    });
  }).run();  
}

私はちょうど同様の問題に遭遇しました、そしてこれは私のために働きました。しかし、私が言わなければならないのは、私はこれに非常に慣れていないので、これがどのように行われるべきかわからないということです。

挿入ステートメントをファイバーでラップするだけでうまくいく可能性がありますが、私は前向きではありません。

于 2012-04-18T04:00:17.707 に答える
7

私のテストに基づいて、上記の例と同様に、私がテストしたコードで挿入をラップする必要があります。

たとえば、私はこれを行いましたが、それでもファイバーエラーで失敗しました。

function insertPost(args) {
  if(args) {
Fiber(function() { 
    post_text = args.text.slice(0,140);
    T.post('statuses/update', { status: post_text }, 
        function(err, reply) {          
            if(reply){
                // TODO remove console output
                console.log('reply: ' + JSON.stringify(reply,0,4));
                console.log('incoming twitter string: ' + reply.id_str);
                // TODO insert record
                var ts = Date.now();
                id = Posts.insert({
                    post: post_text, 
                    twitter_id_str: reply.id_str,
                    created: ts
                });
            }else {
                console.log('error: ' + JSON.stringify(err,0,4));
                // TODO maybe store locally even though it failed on twitter
                // and run service in background to push them later?
            }
        }
    );
}).run();
  }
}

私はこれを行い、エラーなしで正常に実行されました。

function insertPost(args) {
  if(args) { 
post_text = args.text.slice(0,140);
T.post('statuses/update', { status: post_text }, 
    function(err, reply) {          
        if(reply){
            // TODO remove console output
            console.log('reply: ' + JSON.stringify(reply,0,4));
            console.log('incoming twitter string: ' + reply.id_str);
            // TODO insert record
            var ts = Date.now();
            Fiber(function() {
                id = Posts.insert({
                    post: post_text, 
                    twitter_id_str: reply.id_str,
                    created: ts
                });
            }).run();
        }else {
            console.log('error: ' + JSON.stringify(err,0,4));
            // TODO maybe store locally even though it failed on twitter
            // and run service in background to push them later?
        }
    }
);
  }
}

私はこれがこの問題に遭遇する他の人を助けるかもしれないと思いました。内部コードの後に​​非同期タイプの外部サービスを呼び出し、それをファイバーでラップすることはまだテストしていません。それもテストする価値があるかもしれません。私の場合、ローカルアクションを実行する前に、リモートアクションが発生したことを知る必要がありました。

これがこの質問スレッドに貢献することを願っています。

于 2012-05-06T13:17:59.310 に答える