Javascript 为什么这个路由逻辑没有找到已经创建的文档,而是创建新的、重复的文档?

Javascript 为什么这个路由逻辑没有找到已经创建的文档,而是创建新的、重复的文档?,javascript,mongodb,meteor,iron-router,Javascript,Mongodb,Meteor,Iron Router,当路由到特定URL/X时,我想将名为X的“频道”项插入Mongo.Collection,但仅当在数据库中找不到名为X的项时。否则,它应该从数据库中获取该项,并将其作为数据传递,以使用它呈现我的通道页面模板 Channels = new Meteor.Collection('channels'); Router.route('/:channelName', { name: 'channelPage', template: 'channelPage', data: function()

当路由到特定URL
/X
时,我想将名为
X
的“频道”项插入
Mongo.Collection
,但仅当在数据库中找不到名为
X
的项时。否则,它应该从数据库中获取该项,并将其作为
数据
传递,以使用它呈现我的
通道页面
模板

Channels = new Meteor.Collection('channels');

Router.route('/:channelName', {
  name: 'channelPage',
  template: 'channelPage',
  data: function() {
    var currentChannelName = this.params.channelName.toLowerCase();
    var channelInDB = Channels.findOne({
      name: currentChannelName
    });
    if (channelInDB === undefined) {
      Channels.insert({
        name: currentChannelName
      });
      return Channels.findOne({
        name: currentChannelName
      });
    } else {
      return channelInDB;
    }
  }
});
每次我转到
/X
页面时,
data
函数似乎运行两次。第一次
(channelInDB==未定义)
true
。即使集合中已经有一个带有
{name:“X”}
的“通道”项。因此,每次我请求页面时,都会插入一个名为
X
的新项目。
还尝试在
onBeforeAction
hook中执行检查,但没有帮助。
我遗漏了什么,如何解决这个问题


更新

我把
upsert
移动到
Meteor.methods
我首先应该做的事情。我的代码现在如下所示:

Router.route('/:channelName', {
  name: 'channelPage',
  template: 'channelPage',
  data: function() {
    var currentChannelName = this.params.channelName.toLowerCase();
    var channelId = Meteor.apply('callChannelPage', [currentChannelName], {
      wait: true
    });
    console.log(channelId); //undefined
    return channelId;
  }
});

if (Meteor.isServer) {
  Meteor.methods({
    'callChannelPage': function(channelName) {
      Channels.upsert({name: channelName}, {$set: {name: channelName}});
      var result = Channels.findOne({name: channelName}, {fields: {_id: 1}});
      return result._id;
    }
  });
}
我使用了
Meteor.apply
{wait:true}
选项,而不是
Meteor.call
来等待响应,但在路由运行时它仍然返回
未定义的

我知道Meteor.method是有效的,因为当我使用
asyncCallback
运行
调用时,它返回正确的
ChannelId

Meteor.call('callChannelPage', currentChannelName, 
  function(error, results) {
    console.log(results); //tfdaczfnZgwycFDtv
  });
如何在路由器运行时获取它,以便我可以使用模板中的数据


解决方案

我当前的解决方案是仅基于channelname在
channelPage.helper
中获取频道数据

Router.route('/:channelName', {
    name: 'channelPage',
    template: 'channelPage',
    data: function() {
        var channelName = this.params.channelName.toLowerCase();
        Meteor.call('callChannelPage', channelName);
        return {channelName: channelName};
    }
});

//isClient
Template.channelPage.helpers({
    'name': function() {
        return this.channelName;
    },
    'channelId': function(){
        return Channels.findOne({name: this.channelName})._id;
    },
});

//isServer
Meteor.methods({
    'callChannelPage': function(channelName) {
        Channels.upsert({name: channelName}, {$set: {name: channelName}});
    }
});

通过这种方式,模板呈现,来自集合的数据看起来有点延迟。这对我来说很好,但这是正确的方法吗?

这只会在直接访问该URL时发生吗?或者当您使用
Router.go('channelPage',{channelName:'X'})
时会发生这种情况吗?您的频道订阅是什么样子的?别忘了,只有当文档不存在时,您才能自动插入。这将为您节省一些代码。@challett
Router.go('channelPage',{channelName:'X'})
工作正常。但是我需要比
channelName
更多的
channelPage上的数据。我是否应该将每个URL路由到
channelPage
并使用
Template.channelPage.handers
获取数据?@Jahx您可以根据需要添加更多参数。但我不知道你的意思。能否将您对频道集合的订阅添加到您的问题中?在“路由器数据”功能中返回的任何内容都将在模板帮助程序中的
下提供。除了返回数据中的对象之外,我没有尝试过返回任何东西。如何从助手处访问channelID?@challett此时我使用
autopublish
unsecure
软件包。我当前的解决方案是仅基于channelname在
channelPage.helper
中获取频道数据。(见更新)