EugeneMi
EugeneMi

Reputation: 3575

What are the best practices for pre-fetching in backbone.js?

What's the best way to pre-fetch the next page in backbone.js? Is there a build-in mechanism to do that, or do I have to take care of it myself by making Ajax calls and storing the results. Also, is there a way to preload the entire page like in JQuery mobile( http://jquerymobile.com/demos/1.2.0/docs/pages/page-cache.html)

Upvotes: 2

Views: 459

Answers (3)

Meistro
Meistro

Reputation: 3794

There is no built in support for a such a thing. It's dependent on your use case but you could do a number of things.

1) Use setTime() to wait a short time before fetching the data you might be needing shortly. (Probably not a good solution)

2) Set up an event handler to fetch the data on a specific event, or something similar:

$('#my-button').on('hover',function() { 
//fetch data
});

To fetch the data you can use the fetch() function on a backbone model or collection, which will return a jqXHR (or you can use a straight $.ajax() call). You can then wait and see if it failed or passed:

 var fetch = myModel.fetch();
 fetch.done(function(data) {
   // Do something with data, maybe store it in a variable than you can later use
 })
 .fail(function(jqXHR) {
   // Handle the failed ajax call
   // Use the jqXHR to get the response text and/or response status to do something useful

 });

Upvotes: 2

talfco
talfco

Reputation: 111

Here my way how I handle the loading of pages into an "endless scrolling" list.

Make you backend paginate aware

First of all you require a DB backend which is capable of handlling page load requests: As an example refer to my git modelloader project which provides a small Coffee based framework integrated into a Node.js/Moongoose environment.

Model Loader on GIT will contain additional information and samples.

Here the most important points:

You backend should support the following Pagination features

Each request will return partial response only limiting it to for example 20 records (size of a page).

By default the last JSON record entry returned by a request, will contain additional technical and meta information about the request, necessary for allowing consumers to implement a paging.

{
    _maxRec: "3",
    _limit: "20",
    _offset: "0"
}
  • _maxRec will list the total amount of records in the collection
  • _limit will list the maximum number of requests which are given back
  • _offset will tell you which set of records was passed back, i.e. an _offset of 200 would mean that result list skipped the first 199 records and presents the records from 200-220

The backend should support the following pagination control parameters:

http(s)://<yourDomainName>/<versionId</<collection>?offset=<number>

Use offset to skip a number of records, as for example with a limit of 20, you would send a first request with offset=0 then offset=20, then offset=40 etc. until you reached _maxRec.

In order to reduce the db activities you should provide a possiblity to reduce the _maxRec calculation for subsequent requests:

http(s)://<yourDomainName>/<versionId</<collection>?maxRec=<number>

By passing in a maxRec parameter (normally the one gotten by an earlier paging requerst), the request handler will by pass the database count objects statement, which results in one db activity less (performance optimization). The passed in number will passed back via _maxRec entry. Normally a consumer will fetch in the first request the _maxRec number and pass it back for the subsequent request, resulting in a faster data access request.

Fire of Backbone Model requests if necessary

So now you have to implement on the Backbone side the firing of page loading requests when necessary.

In the example below we assume to have a Backbone.View which has a list loaded into a jquery.tinyscrollbar based HTML element. The list contains the first 20 records loaded via the URL when built up initially:

http(s)://<yourDomainName>/<versionId</<collection>?offset=0

The View would listen in this case to the following scrolling events

events:
 'mousewheel': 'checkScroll'
 'mousemove': 'checkScroll'

Goal is as soon the user has scrolled down to the bottom of the scrollable list (e.g. he reaches a point which is 30px above the scrollable list end point) a request will be fired to load the next 20 entries. The following code sample desrcribes the necessary step:

checkScroll:  () =>
    # We calculate the actual scroll point within the list
    ttop =   $(".thumb").css("top")
    ttop = ttop.substring(0,ttop.length-2)
    theight =  $(".thumb").css("height")
    theight = theight.substring(0,theight.length-2)
    triggerPoint = 30 # 30px from the bottom
    fh =  parseFloat(ttop)+parseFloat(theight)+triggerPoint
    # The if will turn true if  the end of the scrollable list
    # is below 30 pixel, as well as no other loading request is 
    # actually ongoing
    if fh > @scrollbarheight && ! @isLoading && @endLessScrolling
        # Make sure that during fetch phase no other request intercepts
        @isLoading = true
        log.debug "BaseListView.checkscroll "+ ttop + "/"+ theight + "/"+ fh
        # So let's increase the offset by the limit
        # BTW these two variables (limit, offset) will be retrieved 
        # and updated by the render method when it's getting back 
        # the response of the request (not shown here)
        skipRec = @offset+@limit
        # Now set the model URL and trigger the fetch
        @model.url = @baseURL+"?offset="+skipRec+"&maxRec="+@maxRec
        @model.fetch 
            update: true
            remove: false
            merge: false
            add: true
            success: (collection, response, options) =>
                # Set isLoading to false, as well as 
                # the URL to the original one
                @isLoading = false
                @model.url = @baseURL
            error: (collection, xhr, options) =>
                @isLoading = false
                @model.url = @baseURL 

The render method of the view will get the response back and will update the scrollable list, which will grow in size and allows the user again to start scrolling down along the new loaded entries.

This will load nicely all the data in a paged manner.

Upvotes: 0

Alexander Beletsky
Alexander Beletsky

Reputation: 19831

No build-in support, but actually easy to add. Please referer to the concept of View Manager, it is able to handle both "view-keeping" tasks and transitions.

In short, the concept is: view manager is component, which is reposible for switching from one application view to another. It will dispose existing view, so it prevents zombies and memory leaks. As well it could handle transitions between view switch.

Upvotes: 0

Related Questions