Javascript Meteor helper函数总是在Meteor.startup()之前调用,并调用两次而不是一次

Javascript Meteor helper函数总是在Meteor.startup()之前调用,并调用两次而不是一次,javascript,node.js,mongodb,meteor,meteor-blaze,Javascript,Node.js,Mongodb,Meteor,Meteor Blaze,在我非常简单的meteor项目中,客户端助手函数被调用了两次 项目中的三个文件是: websites.js:MongoDB集合作为模型类 image\u share.html:包含Blaze模板 image\u share.js:包含blaze模板的帮助函数 Helper函数网站被调用两次,本应调用一次。 虽然我在Meteor.startup()上填充mongoDB集合网站,但集合在第一次调用中显示0项,在第二次调用中显示5项 所以问题是,为什么helper函数在Meteor.startup()

在我非常简单的meteor项目中,客户端助手函数被调用了两次

项目中的三个文件是:

websites.js:MongoDB集合作为模型类

image\u share.html:包含Blaze模板

image\u share.js:包含blaze模板的帮助函数

Helper函数
网站
被调用两次,本应调用一次。 虽然我在
Meteor.startup()
上填充
mongoDB
集合
网站
,但集合在第一次调用中显示0项,在第二次调用中显示5项

所以问题是,为什么helper函数在Meteor.startup()之前被调用,为什么它被调用两次并在不同的调用中返回不同的值

以下是完整的代码:

websites.js:

export const Websites = new Mongo.Collection("websites");

Meteor.startup(function(){
  if(Meteor.isServer){
    Websites.remove({});
    for(i = 0; i < 5; i++)
      Websites.insert({
        "x": "this is a sample text"
      });
  }
});
以下是目录结构的完整项目:

以下是带有控制台日志的浏览器中的输出:

将代码放入客户机上的Meteor.startup并不意味着它将在任何其他代码之前运行,它不会阻塞

由于反应性,助手运行两次。它首先在加载页面时运行,然后在数据库中添加文档时重新运行


如果您想确保db不是空的,请将设备移动到服务器端Meteor.startup

实际上,是您的日志行导致帮助程序重新运行

注意:由于这是一个初学者级别的问题,所以我不想在这里详细讨论,但我会尽量做到精确

TL;博士 它运行了两次,因为第一次呈现模板时没有数据。它与服务器上的Meteor.startup()无关


Meteor中的模板助手是。这些计算跟踪反应性数据源,例如DB查询游标(例如,
Websites.find().count()
返回的游标)

当计算中的某些内容发生更改(无效)时,计算将重新运行。这是通过使用Meteor的幕后操作实现的

你的情况如何 页面加载时,本地客户端的集合为空。客户端会订阅这些集合(或者,如果您使用的是
autopublish
包,则会自动为您创建订阅-这对生产应用程序来说并不是一件好事)

这是第一次呈现模板时,因此帮助程序运行时会产生一组空记录,但由于您有一个反应式数据源(调用
count()
),因此它会对其进行监视

您的服务器可能一直都有这些数据,只是您的客户端还没有这些数据。

一段时间后,数据从订阅中到达,集合被更新,并注意到正在跟踪的计数现在不同,因此计算无效并重新运行帮助程序。这一次客户端已经有了数据,结果是一组5个文档。它仍然监视光标的更改

如果以某种方式(例如,通过Meteor方法调用)在服务器上添加新记录或删除现有记录,则发布将知道该记录并将新数据发送到客户端

然后将更新客户端的集合并使计数计算无效,这将使助手中的计算无效,并导致助手重新运行并再次查询集合

如果我只从帮助器返回光标会怎么样
在这种情况下,Blaze(模板库)将监视光标本身(通过观察它),并且只以更精细的方式执行所需的更改。

那么问题是什么?@RamilMuratov问题是为什么在Meteor.startup()之前调用helper函数为什么会被调用两次?谢谢你的解释!我猜有一个名为miniMongo的包,负责将客户端数据库与服务器同步。但是每次我刷新页面时,它都显示列表大小为0,不明白正确的解释是什么?miniMongo是MongoDB API。集合由Meteor的发布/订阅机制同步。它需要在每次加载页面时接收数据,MiniMongo没有现成的持久性。
<head> <title>courseraNewsAgg</title></head>
<body>
    {{> websiteList}}
</body>

<template name="websiteList">
  <h2 >Items: </h2>
    {{#each webSites}}
        <div>
           {{x}}
         </div>
    {{/each}}
</template>
import { Template } from 'meteor/templating';
import { ReactiveVar } from 'meteor/reactive-var';
import {Websites} from "/import/websites.js";

Template.websiteList.helpers({
  webSites: function(){
    console.log("list size = " + Websites.find().count());
    return Websites.find();
  }
});