0.1.1 • Published 9 years ago

@ra5mus/eb-datastore v0.1.1

Weekly downloads
1
License
ISC
Repository
github
Last release
9 years ago

eb-datastore

The DataStore is both a way to handle network requests againts server-side APIs – and an offline cache on the user-side. It's AJAX, indexedDB and localStorage combined.

The cache will attempt to use indexedDB, but will degrade gracefully and fall back to using localStorage or no offline cache at all – as determined by the capabilities of the user's browser.

All fetch() methods will return a Promise object as a way of handling the asynchronous nature of both netowrking and indexedDB. All watch() methods till return an Observer object, on which the method notify() will be called, whenever the cached data expires and is refreshed automatically from the server-side state.

##Useage

The DS object wrap the to main classes, API and Endpoint. the API class is more of a convenience than anything else – a way of bundling multiple Endpoint objects together, but Endpoint objects can be used just fine on their own. There are even some convenience methods you can use directly on the DS module without instantiating anything, though they offer less flexibility.

Example using API class

  var weatherAPI = new DS.API({
    baseUrl: 'http://vejretapi.ekstrabladet.dk/v2/'
  });

  weatherAPI.defineEndpoint({
    name:'weather',
    url:'{baseUrl}weather/{geoid}[/{days}][/{intervals}]',
    validfor: 10 * DS.MINUTES
  });

  weatherAPI.weather.fetch({
    geoid: 2618425,
    days: '1-7',
    intervals: 24
  }).then(function(data){
    console.log(data);
  });

Okay, so a few things are going on here, which we'll go through.

First we create an API instance and add some properties to it – the most useful one will probably be baseUrl, the naming is entirely optional as long as you're consistent.

Next we define an Endpoint on our API instance by way of the defineEndpoint method. The properties name and url are mandatory while validfor (which determines for how long the object will be cached on the client) will default to ten minutes if not specified. The url property string is in a template format, which works much like other template strings – the curly braces contain variable names that will get replaced with values on initiating the network request. The variables come from the combined options of the call to fetch(options), the options given to the defineEndpoint method AND the options from the initial instantiation of the API object. Values in the fetch(options) will overwrite those in the Endpoint and API, values in the Endpoint will overwrite those in the API. So in our case, the combined options are:

{
  baseUrl:   'http://vejretapi.ekstrabladet.dk/v2/',             // <-- weatherAPI
  name:      'weather',                                          // <-- weather Endpoint
  url:       '{baseUrl}weather/{geoid}[/{days}][/{intervals}]',  // <-- weather Endpoint
  validfor:  10 * DS.MINUTES,                                    // <-- weather Endpoint
  geoid:     2618425,                                            // <-- call to fetch
  days:      '1-7',                                              // <-- call to fetch
  intervals: 24                                                  // <-- call to fetch
}

So upon interpolation, the finished url will become:

http://vejretapi.ekstrabladet.dk/v2/weather/2618425/1-7/24

Now, the square brackets around some of the interpolation expressions, like [/{days}] for instance, simply mean that if the days variable cannot be resolved, everything in the scope of the square brackets will be omitted from the result. In this case it just means that the initial / would also be omitted from the final url string. This is convenient in some apis.

The main advantage to using the API class and adding Endpoint objects to it via the defineEndpoint() method is that the resulting weatherAPI object becomes a single “thing” you can pass around inside your app – all the endpoints are accessible directly from this single object. You could have just as easily made a simple object like var a = {} and added your endpoints directly to that, so using the API class is just a convenience pattern.

Example using observe() method

The DataStore also has a mechanism for polling the server for its current state. It's done almost identically to a fetch(), but the returned object, instead of being a Promise with a then() method, it's an Observer with a notify() method. Basic Observer Pattern.

myObserver = weatherAPI.weather.observe({
  geoid: 2618425,
  days: 0,
  intervals: 24,
  validfor: 5 * DS.MINUTES
})
.notify(function(data){
  // This is called everytime the data updates from
  // the server. In this case every five minutes.
});