Подтвердить что ты не робот

Идеальный способ бесконечного прокрутки и обновления в реальном времени в Метеор

У меня есть большой набор данных, которые я хотел бы разбить на разделы, загруженные бесконечным прокруткой в ​​Meteor, чтобы не допустить загрузки большого набора данных одновременно; вместо этого я бы загрузил куски набора данных, когда это было необходимо. Как это сделать, сохраняя при этом обновления в реальном времени в каждом разделе, загруженные бесконечным прокруткой?

4b9b3361

Ответ 1

Вот код, который я использую для игровой площадки базы данных фильмов. Я экспериментировал с событиями jQuery, но, наконец, решил, что этого достаточно, если данные передаются непрерывно. Моя коллекция тестов - 680 записей, с 20 полями и одним миниатюрным полем, которое составляет от 10 до 20 килобайт на крышку. Здесь код Coffeescript:

Movies = new Meteor.Collection("movies")
if Meteor.isClient
  # starting with 10 items that the user sees a page fast
  Session.set("queryLimit", 10)

  # getting the item count from the server collection
  Meteor.call 'getMoviesCount', (err, result) =>
    Session.set('itemsInQuery',result)
  # subscribe to a subset of the collection, and change the Session var on completion
  # automatically changing the limit of the publishing function with autorun
  Meteor.autorun ->
    Meteor.subscribe "MoviesList", Session.get("queryLimit"),  onComplete = ->
      if Session.get("queryLimit") < Session.get('itemsInQuery')
        queryLimit = Session.get("queryLimit") + 30 #change iterator depending on result size 
        Session.set("queryLimit", queryLimit )

  # Client helper to add more items to handlebars template
  Template.app.helpers movies: ->
    Movies.find({})

if Meteor.isServer
  Meteor.publish "MoviesList", (limit) ->
    # show whole collections once limit is reached, by setting limit to 0
    limit = 0 if limit > Movies.find().count() 
    console.log new Date(), limit
    Movies.find({}, { limit: limit, fields: {title:1 } } ) #use fields to test different result sizes  

  Meteor.methods
    getMoviesCount: (query) ->
      return Movies.find().count()

И html:

<body>
  {{> app}}
</body>
<template name="app">
    {{#each movies}}
      <p>{{title}}</p>
    {{/each}}
</template>

Я сделал несколько быстрых тестов производительности, и выяснилось, что для нескольких строк текста на запись самый быстрый способ отправить данные клиенту - это ограничение около 100. Я также попробовал его с 10-20-килобайтными эскизами, которые встроены в файле. При использовании больших активов Chrome стал совершенно не реагировать, когда предел превысил 30 записей. Вот несколько статистических данных, сделанных на localhost (запустите 3 раза каждый):

limit   seconds till last record rendered.
  0     79s 
  010   121s
  020   64s  
  030   45s
  050   34s
  100   16s
  200   16s

Интересно отметить, что около 79 с, когда метеоритный сервер отправляет всю страницу за один проход (limit = 0). Я не уверен, как это возможно, потому что непрерывный поток должен быть самым быстрым. Поэтому, наверное, что-то смешное в моей статистике. Есть идеи?

Ответ 2

Мое решение похоже на Андрея. Поскольку у меня много записей в базе данных, я не хочу, чтобы мой сервер отправлял их все сразу, поэтому на сервере я получил:

Meteor.publish("items", function(page) {
    if(!page)
        page = 1;
    var limit = 30 * page;
    return Items.find({}, {limit: limit};
}

Клиент:

Template.templateName.items = function () {
    Meteor.subscribe("items", Session.get("page"));
    return Items.find({});
}

И функция jQuery для наблюдения, если страница была снизу:

$(window).scroll(function(){
    if ($(window).scrollTop() == $(document).height()-$(window).height()){
        Session.set("page", Session.get("page") + 1);
    }
});

Также для установки начальной страницы страницы в созданном шаблоном обратном вызове:

Template.templateName.created = function() {
    Session.setDefault("page", 1);
};

И в шаблоне я показываю эти элементы, используя {{#each}} Кроме того, я должен проверить, нет ли записей

Лучшее решение будет состоять в том, чтобы показать 30 при создании шаблона и после этого получить еще 30 прокруток, но я не знаю, как их показать. У меня может быть решение, но я ленив, чтобы реализовать, потому что я не уверен, что это сработает. Я думаю о добавлении отображаемого html

Ответ 3

Вы можете установить ключ сеанса, в котором хранится какая страница, на которой вы сейчас находитесь. Что-то вроде:

Session.set("cur_page", 1);

И затем вы отправите это в свой запрос, например:

Template.list.items = function() {
  return Collection.find({}, {
    skip: Session.get("cur_page") * page_size,
    limit: page_size
  });
}

Затем вы просто обновляете значение с помощью Session.set("cur_page", 2), и ваш список будет перерисовываться с элементами на стр. 2. Tadaa!

Ответ 4

Я еще не пробовал этого, но он должен работать. Итак, если у вас есть ваша коллекция:

var Posts = new Meteor.Collection("posts");

И ваш шаблон:

<template name="posts">
    {{#each posts}}
        {{> post}}
    {{/each}}
</template>

Это может быть ваш шаблон-помощник:

Template.posts.helpers({
    posts: function() {
        return Posts.find({}, {limit: Session.get("current_page")*PAGE_SIZE});
    }
});

где PAGE_SIZE - количество сообщений на "страницу". Каждый раз, когда пользователь прокручивается в нижней части страницы, вам необходимо увеличить переменную сеанса "current_page". Затем шаблон будет обновлен, и ваш inifnite scroll (надеюсь) работает!