1

我有一个流星应用程序,其中有 2 个帖子出版物。一个用于所有帖子,一个用于特色帖子。有 2 个精选帖子 - “帖子 1”和“帖子 4”。我在所有页面上显示精选帖子,同时按名称对所有帖子(包括精选帖子)进行分页。当我在页面之间旅行时,来自 2 个出版物的数据会混淆并显示不正确的结果。

这是代码:

Meteor.publish('posts', function(page) {
  const skip = parseInt(page && page !== '' ? page : 0) * 3
  return Posts.find({}, {
    limit: 3,
    skip,
    sort: {
      name: 1
    }
  });
});

Meteor.publish('featured', function() {
  return Posts.find({
    featured: true
  }, {
    sort: {
      name: 1
    }
  });
});

在客户端上,我同时订阅并在 2 个循环中显示数据

Template.hello.onCreated(function helloOnCreated() {
  const instance = this;
  instance.autorun(function() {
    instance.subscribe('posts', FlowRouter.getParam('page'))
    instance.subscribe('featured')
  });
});

Template.hello.helpers({
  posts() {
    return Posts.find({}, {
      limit: 3,
      sort: {
        name: 1
      }
    })
  },
  featured_posts() {
    return Posts.find({
      featured: true
    }, {
      sort: {
        name: 1
      }
    });
  }
});

HTML模板如下:

<template name="hello">
  <h2>Featured</h2>
  {{#each featured_posts}}
    {{> post}}
  {{/each}}
  <h2>Posts</h2>
  {{#each posts}}
    {{> post}}
  {{/each}}
</template>

问题是来自 2 个订阅的数据在显示中混淆了。

在第 1 页上,它正确显示:

Page 1

Featured
  post 1
  post 4

All Posts
  post 1
  post 2
  post 3

但是当我转到第 2 页时

Page 2

Featured
  post 1
  post 4

All Posts  -- Should be
  post 1        post 4
  post 4        post 5
  post 5        post 6

它在“帖子”中显示“帖子 1”,这是特色但不应该出现在第 2 页上。当我转到第 3 页时,我看到“帖子 1”和“帖子 4”,但它们不应该在那里。

我了解出版物和订阅是如何工作的,以及为什么会发生这种情况——因为出版物合并了数据集。我想知道是否有办法让它们分开?

4

2 回答 2

1

如果我理解正确,您的页面对应于您的“所有帖子”列表的分页。“页”号作为您的订阅参数发送,以便您收到您的帖子的简短列表。

这里的困难确实是您的 Client 集合中没有您所有的文档(因为您在'posts'出版物中限制了它们),因此您不能使用与skip出版物中类似的逻辑。

正如 Meteor Guide > Paginating subscriptions中所建议的那样,您可以使用percolate:find-from-publicationAtmosphere 包轻松检索来自您的'posts'出版物的文档,并且只检索它们。

// Server
FindFromPublication.publish('posts', function(page) {
  // Same logic
  const skip = parseInt(page && page !== '' ? page : 0) * 3
  return Posts.find({}, {
    limit: 3,
    skip,
    sort: {
      name: 1
    }
  });
});

// Client (no change in subscription)
Template.hello.helpers({
  posts() {
      return Posts.findFromPublication('posts', {}, {
        sort: {
          name: 1
        }
      });
    } // (no change in featured_posts)
});
于 2017-05-16T17:08:52.013 回答
1

我建议使用observeorobserveChanges以便可以在客户端上隔离正在发布的数据。文档可能令人生畏,但实际上比看起来要容易。

只需创建一个特殊的客户端集合,然后在观察回调中使用该集合的名称即可。请注意,客户端集合名称 ,"featured_posts"用于对 的调用self.addedself.changed发布self.removed中:

// client-side
const FeaturedPosts = new Mongo.Collection('featured_posts', {
  defineMutationMethods: false
});

// server-side
Meteor.publish('featured', function() {
    const self = this;

    const handle = collection.find(selector, opts).observe({
      added: function(doc) {
        self.added('featured_posts', doc._id, doc);
      },

      changed: function(newDoc, oldDoc) {
        self.changed('featured_posts', newDoc._id, newDoc);
      },

      removed: function(doc) {
        self.removed('featured_posts', doc._id);
      },
    });

    self.ready();

    self.onStop(function(err) {
      if (!err) {
        handle.stop();
      }
    });
  });
};
于 2017-05-16T18:07:42.353 回答