"Chaining" 流星订阅

"Chaining" Meteor subscriptions

我正在使用 React 和 createContainer。我正在寻找一种可以将两个调用链接在一起的方法。

例如,如果我有这个数据:

// Category
{
   _id: 'ABC',
   name: 'Cat 1'
}

// Item
{
   catId: 'ABC',
   slug: 'slug'
}

在我的 createContainer 中,我想通过 slug (Items.find({ slug })) 获得 Item。然后我想转身并通过 item.catId.

获取类别

我试过类似的方法,但没有用:

 createContainer(({ slug }) => {
     const itemHandler = Meteor.subscribe('Item.bySlug', slug);
     const item = Items.findOne();

     const categoryHandler = Meteor.subscribe('Category.byId', (item.id || {}).id); // also tried just item.id and got undefined for item
     const category = Categories.findOne();

     return { item, category };
 }, Component);

我可以得到 item 就好了,但是 category 没有骰子,它仍然未定义。我确定我没有被动触发某些东西,但我不太确定在这种情况下正确的模式是什么,或者是否有更简化的方式。

您实际上是在进行客户端连接。在这些情况下,我通常会进行服务器端连接。在这里,在 Item.bySlug 发布者中,我会做这样的事情:

let itemCursor = Items.find({slug: slug});

let transformItem = (fields) => {
    // making an assumption here that Item has a categoryId that indicates its category
    let category = Categories.findOne(fields.categoryId);

    // attach the category to the Item
    fields.category = category;

    return fields;
};

let handle = itemCursor.observeChanges({
    added: (id, fields) => {
        fields = transformItem(fields);
        this.added('items', id, fields);
    },
    changed: (id, fields) => {
        fields = transformItem(fields);
        this.changed('items', id, fields);
    },
    removed: (id) => {
        this.removed('items', id);
    }
});

this.ready();

this.onStop(() => {
    handle.stop();
});

现在,在客户端,你只需要订阅你想要的Item,它的类别就会被附加。

解决您问题的最简单方法是从服务器端 publication return cursorsarray 并在客户端调用 collection.findOne()subscription.

之后

发布代码应该是这样的:

Meteor.publish("your.publication.name", function(slug, id){
    let itemCursor = Items.find(your_selector);
    let categoryCursor = Categories.find(your_selector);
  return [itemCursor, categoryCursor];
});

现在您将从客户端的项目和类别集合中获取必要的文档。

事实证明,我发布的代码确实有效,我只是遇到了一个数据问题,其中 Items.categoryId 没有被正确填充。

在这个特定的例子中,我确实想进行客户端连接,我所做的确实有效。项目位是反应的,一旦加载,它实际上会重新运行然后正确填充该字段。

createContainer(({ slug }) => {
     const itemHandler = Meteor.subscribe('Item.bySlug', slug);
     const item = Items.findOne();

     const categoryHandler = Meteor.subscribe('Category.byId', (item.id || {}).id); // also tried just item.id and got undefined for item
     const category = Categories.findOne();

     return { item, category };
 }, Component);

第一个 运行 到 item 将被定义,而 category 将为空。下一次检查(一旦 item 准备就绪)将填充 category。需要跳两步,但效果很好。