URL 解析在 Meteor.startup 中不起作用

URL Parsing not working within Meteor.startup

本文关键字:startup 不起作用 Meteor URL      更新时间:2023-09-26

我有一个函数,它接受一个字符串,并根据在集合中查找文档来设置会话。在这种特殊情况下,字符串是游戏name的可能名称,我将会话设置为该游戏的_id

问题是当我将其绑定到模板事件时,该函数完全按预期工作,但是当我在 Meteor.startup 中调用该函数时根本不起作用。仅供参考 - 截至目前,我正在运行自动发布。(我计划在此步骤之后调整发布/订阅设置。

这是获取字符串并适当设置会话的函数:

var enterExisting = function(n) {
    var g = Games.findOne({name:n});
    var e = "That game doesn't exist.";
    Session.set("error", null);
    Session.set("no_game", null);
    if (Validation.game_exists(n)){
        Validation.clear();
        Session.set("current_game", g._id);
        window.location.hash = ("/" + n);
    } else {
        Session.set("error", e)
    }
};

在主页上,我在表单上使用此功能,它按预期工作。它设置会话、显示游戏并更改 URL。这是它在该表单上的使用方式:

Template.entergame.events({
    'click input.enter-game': function(){
    var n = document.getElementById('enter-game-name').value;
    enterExisting(n);
}
});

当我尝试在Meteor.startup上以类似的方式使用相同的功能时,它不会设置会话或指导我。

Meteor.startup(function () {
    Session.set("current_game", "");
    Session.set("error", null);
    Session.set("no_game", null);
    var n = location.hash.substring(2);
    if (n.length === 0) {
        window.location.hash = "#/"
    } else {
        enterExisting(n);
    }
});

我不希望它是相关的,但以防万一,这是"加入游戏"表单的模板:

<template name="entergame">
    <div class="enter-game">
        {{#if error}}
          <p class="error bad-entry">
            {{error}} 
          </p>
        {{/if}}
        <input id="enter-game-name" type="text" placeholder="Join an Existing Game!" />
        <input type="button" class="enter-game" value="»">
    </div>
</template>

如果您将"Meteor.startup"替换为"Template.entergame.created",这应该可以工作

"Meteor.startup"适用于服务器,不会在每次渲染模板时执行。这就是为什么对于每个模板,您都有一个"创建"事件。

Emgee 是对的:您应该使用 iron-router 进行客户端路由(目前没有服务器端)。 特别是因为 iron-router 允许您在渲染时为模板设置默认数据。

回答我自己的问题,因为我确实得到了这个工作,它可能对其他人有用。我进一步改进了笨重的用户体验,但此时,我计划按照 Gorb 博士和 emgee 的建议删除所有这些工作,转而使用铁路由器。如果我模拟从服务器接收数据的长时间延迟,此解决方案就会崩溃。

问题在于发布/订阅时间线,具体而言,我需要等待订阅从服务器接收数据,然后再尝试呈现适当的模板。

第一步是删除自动发布。

接下来,我将 URL 解析函数放入回调中,如下所示:

Meteor.startup(function () {
    Session.set("current_game", "");
    Session.set("error", null);
    Session.set("no_game", null);
    var n = location.hash.substring(2);
    Meteor.subscribe("dice");
    Meteor.subscribe("games", function(){
        if (n.length === 0) {
        window.location.hash = "#/"
        $('.home').fadeIn('slow');
        } else {
        enterExisting(n);
        setTimeout(function(){$('.currentgame').fadeIn('slow')}, 1);
    }});
});

下面是确定在订阅返回数据后要加载哪个模板的回调:

    Meteor.subscribe("games", function(){
        if (n.length === 0) {
        window.location.hash = "#/"
        $('.home').fadeIn('slow');
        } else {
        enterExisting(n);
        setTimeout(function(){$('.currentgame').fadeIn('slow')}, 1);
    }});

使用此解决方案,回调函数

可能会在页面加载后发生,并在加载数据后突然切换模板。所以我添加了一个简单的解决方案:隐藏可能发生变化的部分,并在准备好时淡入正确的模板。

在我的 CSS 中:

.home, .currentgame {display:none;}

在上面的 JS 中,您将看到:

    Meteor.subscribe("games", function(){
        .
        .
        .
        $('.home').fadeIn('slow');
        .
        .
        .
        setTimeout(function(){$('.currentgame').fadeIn('slow')}, 1);
    }});

至于setTimeout,我真的没有解释,但它让它起作用了。(我怀疑这是将该功能排在 Session.set 后面的问题。