【问题标题】:Sporadic behaviour with Session variables in MeteorMeteor 中会话变量的零星行为
【发布时间】:2012-06-03 07:19:01
【问题描述】:

我一直在摸不着头脑,为什么这段代码有时会起作用,但不是全部(或至少大部分时间)。我发现它确实有时会在浏览器中显示正确的内容,但奇怪的是,有几天我会回到相同的代码,运行服务器(正常)并加载页面会在控制台收到错误:TypeError: 'undefined' is not an object (evaluating 'Session.get('x').html')

(当我收到该错误时,有时控制台中的下一行将读取Error - 指的是err 对象,而其他时候它会读取Object - 指的是data对象!?)。

我显然在 Meteor 中遗漏了一些关于 Session 变量的内容,并且一定是在滥用它们?我希望有经验的人能指出我正确的方向。

在此先感谢您的帮助!

这是我的虚拟代码:

/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;

  }

});

【问题讨论】:

    标签: meteor


    【解决方案1】:

    我认为只是在客户端首次启动时尚未设置会话变量。因此,Session.get('x') 将返回 undefined,直到您的方法调用 (foo) 返回,这几乎肯定不会在模板第一次绘制之前发生。

    但之后它将在会话中,因此一旦您刷新,事情可能会正常运行。

    答案是在尝试访问变量之前检查它是否为undefined。例如:

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

    【讨论】:

    • 感谢汤姆的回复。我的印象是,一旦设置了会话变量,它就会自动更新 Session.get 引用。我在上面尝试了你的解决方案,但我得到了同样的错误,一秒钟后在 console.log 中返回了 data 对象。
    • @rs77:是的,它会自动更新。所以将会发生的是Template.hello.greeting 中的代码将针对会话变量采用的每个值进行评估。你只需要小心它永远不会出错;你的代码基本上是正确的,你只需要超过最初的undefined 值。
    • 谢谢汤姆!我想我输入的代码不正确:if (Session.get('x').html)) return Session.get('x').html 但在阅读下面汤姆威斯曼的回复后,我看到了我的方式错误,代码按照你所说的那样工作。我会将您的答案标记为正确的答案,并感谢 Tom Wijsman 的额外见解(我希望我能在你们两个正确的答案中打勾!!)。感谢您的帮助。
    • 这是一个糟糕的解决方案,因为它会将其留空(但未使用)。它应该使用 Session.setDefatult('x', '');而是。
    【解决方案2】:

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

    【讨论】:

    • 再次感谢汤姆的帮助!当我看到您的回复并尝试您的第 1 步(正如汤姆科尔曼建议的那样)时,我发现了错误。我很抱歉成为一个笨蛋!再次感谢。
    猜你喜欢
    • 1970-01-01
    • 2021-02-27
    • 2015-11-05
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2022-01-09
    相关资源
    最近更新 更多