2012-04-17 50 views
38

我在server/statusboard.js中有以下代碼;當調用服務器上的Collection.insert時,「流星代碼必須始終運行在光纖內」

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提要中提取一些數據並嘗試將其推送到集合中。

當我啓動流星我得到以下異常;

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 

我不太確定那個錯誤的含義。有沒有人有任何想法,或可以建議一個不同的方法?

+0

我要清楚的是「服務」已在別處定義在一個單獨的文件(兩者共同的客戶:

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

,如果你想知道更多的關注於事件觸發考慮到這些視頻和服務器)。 – 2012-04-17 14:18:49

+0

這條線是問題: '服務。insert({host:host,service:service,hardState:hardState,currState:currState});' 我認爲它是因爲它在回調中,暫時沒有辦法測試你。 – jonathanKingston 2012-04-17 14:31:24

+2

流星現在包括一個HTTP請求庫,使您的情況更容易:http://docs.meteor.com/#meteor_http – debergalis 2012-05-06 16:13:04

回答

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

我只是碰到了類似的問題,這爲我工作。我不得不說的是,我對此很新,我不知道這是否應該如何完成。

你可能只能將你的插入語句包裝在光纖中,但我不積極。

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

我認爲這可能會幫助其他人遇到此問題。我還沒有測試過在內部代碼之後調用異步類型的外部服務,並將其包裝在光纖中。這可能也值得測試。就我而言,我需要知道在執行本地操作之前發生的遠程操作。

希望這有助於這個問題的線程。

+0

[02:33:57]這是一個不好的答案,我應該對此發表評論。 [02:34:20]確實創建了一個Fibre,但它並沒有在它內部設置有用的meteor上下文,並且實際上並沒有阻塞內部線程上的外部方法。 – 2012-06-07 00:34:26

+2

@TomWijsman這是準確的嗎?在該方法的整個代碼塊周圍的光纖? – 2012-06-07 08:18:29

+1

[01:40:21] 1:解開寫入欄。請參閱軟件包/ meteor/timers.js中Meteor.setTimeout的實現。 [01:41:19] 2:包裝你在新光纖中定義的任何回調,以便該方法在你的回調運行之前不會返回。這就是如何實現同步流星API,就像在包/ mongo-livedata/mongo_driver.js [01:42:02]正確的答案實際上是3:吼我們沒有實現一個像樣的同步API爲任何你試圖要做:) – 2012-06-07 13:37:45

47

將您的功能封裝在光纖中可能不夠,並可能導致意外的行爲。

原因是,隨着光纖,流星需要一組變量附加到光纖。 Meteor使用附加在光纖上的數據作爲動態範圍,使用第三方API的最簡單方法是使用Meteor.bindEnvironmenthttps://www.eventedmind.com/posts/meteor-dynamic-scoping-with-environment-variables https://www.eventedmind.com/posts/meteor-what-is-meteor-bindenvironment

+1

這對我來說是個訣竅。被接受的答案是行不通的,因爲「光纖」不存在! – 2014-05-26 18:28:13

+1

纖維只存在於服務器端,您是將它放在常用的還是客戶端的代碼中? – Thomas 2014-09-28 05:01:55

+1

這應該是公認的答案 – 2015-06-18 06:38:18

相關問題