2012-06-02 35 views
2

我一直在撓撓我的腦海,爲什麼這段代碼會在一段時間內工作,但不是全部(或者至少大部分時間)。我發現它實際上在某些時候運行在瀏覽器中顯示正確的內容,但奇怪的是,我會回到相同的代碼,運行服務器(按照常規)以及加載頁面將在控制檯收到一個錯誤:TypeError: 'undefined' is not an object (evaluating 'Session.get('x').html')流星會話變量的零星行爲

(當我收到錯誤會有次,其中在控制檯下一行會讀Error - 指的是err對象,其他時候,它會讀取Object - 參考data object !?)。

我很明顯錯過了流星中的會話變量,並且必須濫用它們?我希望有經驗的人能指引我走向正確的方向。

非常感謝您的幫助!

這裏是我的虛擬代碼:

/client/del.html 
<head> 
    <title>del</title> 
</head> 

<body> 
    {{> hello}} 
</body> 

<template name="hello"> 
    Hello World! 
    <div class="helloButton">{{{greeting}}}</div> 
</template> 

我的客戶端JavaScript文件是:

/client/del.js 
Meteor.call('foo', 300, function(err, data) { 
    err ? console.log(err) : console.log(data); 
    Session.set('x', data); 
}); 

Template.hello.events = { 
    'click div.helloButton' : function(evt) { 
    if (Session.get('x').answer.toString() === evt.target.innerHTML) { 
     console.log('yay!'); 
    } 
    } 
}; 

Template.hello.greeting = function() { 
    return Session.get('x').html; 
}; 

我的服務器端JavaScript是:

/server/svr.js 
Meteor.methods({ 

    doubled: function(num) { 
    return num * 2; 
    }, 

    foo: function(lmt) { 
    var count = lmt, 
     result = {}; 

    for (var i = 0; i < lmt; i++) { 
     count++; 
    } 

    count = Meteor.call('doubled', count); 

    result.html = "<em>" + count + "</em>"; 
    result.answer = count; 
    return result; 

    } 

}); 

回答

1

我認爲這只是當客戶端首次啓動時,會話變量將不會被設置。因此Session.get('x')將返回undefined,直到您的方法調用(foo)返回,這幾乎肯定不會在模板第一次繪製之前發生。

但是之後它會在會話中,所以一旦刷新,事情可能會正常。

答案是在嘗試訪問變量之前檢查它是否爲undefined。例如:

Template.hello.greeting = function() { 
    if (Session.get('x')) return Session.get('x').html; 
}; 
+0

謝謝湯姆的回覆。我的印象是,一旦會話變量設置爲會自動更新Session.get引用。我在上面嘗試了你的解決方案,之後我在console.log中返回的'data'對象上面得到了同樣的錯誤。 – rs77

+0

@ rs77:是的,它會自動更新。那麼會發生什麼是'Template.hello.greeting'中的代碼將針對會話變量所採用的每個值進行評估。你只需要小心,它永遠不會遇到錯誤;你的代碼基本上是正確的,你只需要通過最初的'undefined'值。 –

+0

謝謝湯姆!我認爲我錯誤地輸入了你的代碼:if(Session.get('x')。html))返回Session.get('x')。html',但是當閱讀下面的Tom Wijsman的回答時,我看到了我的錯誤代碼按照您的說法工作。我會將你的答案標記爲正確的,並且要感謝Tom Wijsman提供的更多見解(我希望我可以勾選你的兩個正確答案!)。謝謝你的幫助。 – rs77

1

一個流星的seven principles的是:

延遲補償。在客戶端上,使用預取和模型仿真,使其看起來像有一個到數據庫的零延遲連接。

由於存在延遲,客戶端首先會根據客戶端連接時的數據繪製佈局圖。然後它會進行呼叫,然後根據呼叫更新。有時候,通話可能能夠快速響應,以便同時進行繪製。因爲現在有可能不設置變量,它會在該場合拋出異常並因此中斷執行(因爲調用堆棧中的函數將不會繼續運行)。

有這兩個可能的解決方案:

  1. 檢查變量使用時設置。

    return Session.get('x') ? Session.get('x').html : '';

  2. 確保變量通過在腳本的頂部設置了初始值。

    Session.set('x', { html = '', answer = ''});

另一種方法是,一旦呼叫響應添加模板。

Meteor.call('foo', 300, function(err, data) { 
    Session.set('x', data); 
    $('#page').html(Meteor.ui.render(function() { 
     return Template.someName(); 
    })); 
}); 
+0

再次感謝湯姆的幫助!當我看到您的回覆並嘗試了第1步時(如Tom Coleman所建議的),我發現了這個錯誤。我很抱歉成爲一個klutz!再次感謝。 – rs77