Providers and selectors methods
This chapter describes all methods common to providers and selectors. If you haven't done it already, we recommend you to first read the Selector API and Provider API to deeply learn what they are, and how to create them.
Methods
read()
Dispatches the read method. In the case of providers, it will dispatch the internal readMethod
implemented by specific origin addons. In case of selectors, it will dispatch the read
method of all needed dependencies and execute the selector function
as described in the Selector API.
When there is no cache for the resource, a readStart
event will be triggered at the beginning, and a readSuccess
event will be triggered at the end (or readError
in case of error). Read the events API chapter for further info.
Returns
(Promise) Promise resolved with the data resultant when reading the provider, or rejected with an Error
.
Example
books.read().then(data => {
console.log("Books result", data);
}).catch(error => {
console.log("Reading books was rejected with error", error);
});
query(queryValue)
Creates a new child instance of the provider and returns it. The new instance will maintain the provided object
as its queryValue
, and will apply it when its read method is called. If an instance with the same queryValue
was created before, then it will returned instead of creating a new one (in order to maintain its cache, config, etc.)
Returned instance will maintain a relation with its "parent" in some way. Internally they are called "children", because when the cache of the "parent" resource is cleaned, all the children caches are cleaned too. (For example, cleaning the cache of an API origin requesting to "/api/books", will also clean the cache of "/api/books?author=2")
Different Provider addons will use the current queryValue
in different ways when consulting the specific data origin (for example, @data-provider/axios will use the queryValue
to define url parameters or query strings when requesting to the API, but @data-provider/browser-storage will access to an specific key of the value saved in the browser storage).
When you use the query
method of a provider or selector that also was created using query
, the resultant queryValue
will be the extension of the provided one and the previous one. In other words, queries are "chainable" and maintain the "scope". See the examples below for better understand.
Arguments
queryValue
(Object): Object to be set asqueryValue
in the returned provider or selector.
Returns
(provider or selector): Queried child instance of the provider (or selector) in which the method was executed.
Examples
Note: next examples are based on providers created with the @data-provider/axios addon.
const book = books.query({ urlParams: { author: 2 }});
book.read(); // Fetch to /books/2
const booksFilteredByYear = books.query({ queryString: { year: 1605 }});
booksFilteredByYear.read(); // Fetch to /books/?year=1605
const booksFilteredByYearAndAuthor = booksFilteredByYear.query({ queryString: { author: 1 }});
booksFilteredByYearAndAuthor.read(); // Fetchs to /books/?year=1605&author=1
books.cleanCache();
// Clean caches of books, booksFilteredByYear, and booksFilteredByYearAndAuthor
addQuery(name, queryMaker)
This methods allows to add custom query
methods to the providers and selectors. This methods are only parsers
receiving a query value, then transform it and call to the original provider query
method with the transformed one. Sounds complicated, but it is easy to understand if you read the purpose and next examples.
Purpose
Origins addons normally require to receive the queryValue
with an specific format when its query
method is called. (For example, the @data-provider/axios addon requires an object containing urlParams
or queryString
properties). This require to know that specific
syntax to pieces building the queries. Normally pieces using providers should be abstracted from the fact of which type of provider are they using, so here is where the addQuery
method enters. It allows to abstract another actors from knowing which is the required format when querying a provider or selector.
Arguments
name
(String): Name of the new custom query method to be defined, which will be accessible asprovider.queries[name]
queryMaker
(Function): Function receiving any value, and returning aqueryValue
ready to be used by thequery
method of the provider or selector.
Returns
(undefined
), but it adds a new method to the queries
object of the provider or selector. When this method is called, it will return a new queried
instance as described in the query
method api. It also adds an entry to the queryMethods
object of the provider containing the queryMaker
for making easier to test the custom queries.
Example
Note: next examples are based on providers created with the @data-provider/axios addon.
// Without using a custom query method:
let book = books.query({ urlParams: { author: 2 }});
book.read(); // Fetch to /books/2
// Definining a custom query method:
books.addQuery("ofAuthor", author => ({ urlParams: { author }}));
// From now, querying by author can be made as:
book = books.queries.ofAuthor(2);
book.read(); // Fetch to /books/2
config(options)
Defines options. Will overwrite those properties already defined in the options
object when the provider or selector was instantiated (read Provider api and Selector api). The resultant configuration will be the extension of the initial options
object and all options previously defined using this method.
There are some options that only have effect when they are defined in the initial options
method, as tags
, initialState
and id
in the case of Selectors. For specific options of addons, please read its own documentation, as each one can define its own configMethod
.
Arguments
options
(Object): Object containing options. Read the Provider api and Selector api pages for further info.
Example
Note: next example is based on a provider created with the @data-provider/axios addon.
books.config({
baseUrl: "http://localhost:3000";
});
cleanCache(options)
Cleans the cache of selector or provider, and also the cleans the cache of all its "children" (queried instances obtained using its query
method). In a practical example, this means that cleaning the cache of an API origin requesting to "/api/books", will also clean the cache of "/api/books?author=2"
A cleanCache
event will be triggered at the beginning. Read the events API chapter for further info.
Arguments
options
(Object): Object that can contain next properties:force
(Boolean): Iftrue
, will force to clean the cache immediately, ignoring thecleanCacheThrottle
option.
Example
books.read(); // Request to /books
books.read(); // Does not request, as Promise is cached.
books.cleanCache();
books.read(); // Request to /books
cleanDependenciesCache(options)
Cleans the cache of all dependencies of a selector. If called on a provider, it only cleans the provider cache (it is equivalent to call to cleanCache
).
Arguments
options
(Object): Object containing options.except
(Array): Array of provider or selectors instances which cache should not be cleaned. Then, all dependencies cache will be cleaned except these.force
(Boolean): Iftrue
, will force to clean the cache immediately, ignoring thecleanCacheThrottle
option.
Example
booksAndAuthors.read(); // Selector reading `books` and `authors` providers. Request to /books and /authors
booksAndAuthors.read(); // Does not request, as Promise is cached.
booksAndAuthors.cleanDependenciesCache();
booksAndAuthors.read(); // As providers cache was cleaned, the selector is read again, and both providers requests are repeated.
booksAndAuthors.cleanDependenciesCache({
except: [books] // Cleans all dependencies cache except the books one
});
booksAndAuthors.read(); // Now only authors provider is read. Books remains cached.
resetState()
Resets the data
, loading
, loaded
and error
state properties to its original state (the ones defined in the initialState
option, or the default ones { data:undefined, error: null }
if no initialState
was defined).
Note: Take into account that this method does not cleans the cache, you have to do it by yourself using the cleanCache
method. Otherwise, you will receive the data when using the read
method, as it is cached, but the data
in the state will remain empty, as it is not being defined again until a read
method is executed with the cache empty.
Example
await books.read();
console.log(books.state);
// { data: [{ title: "Don Quijote " }], loading: false, loaded: true, error: null}
books.resetState();
// { loading: false, loaded: false, error: null}
on(eventName, listener)
Adds listener
to the given eventName
. Read the events API chapter for further info.
Arguments
eventName
(String): Event name to subscribe to.listener
(Function): The callback to be invoked when the specificeventName
is dispatched.
Returns
(Function): A function that unsubscribes the listener
.
Example
books.on("readSuccess", () => {
console.log("Books were successfully read");
});
await books.read();
// Books were successfully read
onChild(eventName, listener)
Adds listener
to the given eventName
when it occurs in any of the provider or selector "children" (queried instances). Read the events API chapter for further info.
Arguments
eventName
(String): Event name to subscribe to.listener
(Function): The callback to be invoked when the specificeventName
is dispatched in any of the selector or provider "children".
Returns
(Function): A function that unsubscribes the listener
.
Example
authorBooks = books.queries.byAuthor(2);
books.onChild("readSuccess", () => {
console.log("Queried books were successfully read");
});
await authorBooks.read();
// Queried books were successfully read
once(eventName, listener)
Adds listener
to the given eventName
. The listener
will be automatically unsubscribed after its first execution. Read the events API chapter for further info.
Arguments
eventName
(String): Event name to subscribe to.listener
(Function): The callback to be invoked when the specificeventName
is dispatched.
Returns
(Function): A function that unsubscribes the listener
.
Example
books.once("readSuccess", () => {
console.log("Books were successfully read");
});
await books.read();
// Books were successfully read
await books.read();
// ...
onceChild(eventName, listener)
Adds listener
to the given eventName
when it occurs in any of the provider or selector "children" (queried instances). The listener
will be automatically unsubscribed after its first execution. Read the events API chapter for further info.
Arguments
eventName
(String): Event name to subscribe to.listener
(Function): The callback to be invoked when the specificeventName
is dispatched in any of the selector or provider "children".
Returns
(Function): A function that unsubscribes the listener
.
Example
authorBooks = books.queries.byAuthor(2);
books.onceChild("readSuccess", () => {
console.log("Queried books were successfully read");
});
await authorBooks.read();
// Queried books were successfully read
await authorBooks.read();
// ...
Getters
state
Returns
(Object): Current state of the provider or selector, containing data
, loading
, loaded
and error
properties.
Example
console.log(books.state);
// { data: [{ title: "Don Quijote " }], loading: false, loaded: true, error: null}
id
Returns
(String): Id of the provider or selector.
Example
books = new Axios("books-from-api", {
url: "/books"
});
console.log(books.id);
// books-from-api
queryValue
Returns
(Object) or (undefined): Value defined to the query
method which created the provider or selector instance. If the instance is a "parent" instance and was not created using the query
method, returns undefined
.
Example
let book = books.query({ urlParams: { author: 2 }});
console.log(book.queryValue);
// { urlParams: { author: 2 }}
queries
Returns
(Object): Returns object containing custom query
methods defined using the addQuery
method.
Example
// Definining a custom query method:
books.addQuery("ofAuthor", author => ({ urlParams: { author }}));
// From now, querying by author can be made as:
book = books.queries.ofAuthor(2);
book.read(); // Fetch to /books/2
children
Returns
(Array): Array containing all children instances created with the query
method. Each element in the array is a provider or selector itself, and contains all methods described in this page.
Example
let book = books.query({ urlParams: { author: 2 }});
console.log(books.children);
// [book]
parent
Returns
(provider), (selector) or (undefined): If the instance was created with the query
method returns the parent instance. If not, returns undefined
.
Example
let book = books.query({ urlParams: { author: 2 }});
console.log(book.parent);
// [books]
options
Returns
(Object): Current options, read the config
method api for further info.
Example
Note: next example is based on a provider created with the @data-provider/axios addon.
books = new Axios("books-from-api", {
url: "/books"
});
books.config({
baseUrl: "http://localhost:3000";
});
console.log(books.options);
// { url: "/books", baseUrl: "http://localhost:3000", tags: ["axios"], id: "books-from-api" }
queryMethods
Returns
(Object): Object containing all custom query methods previously defined using the addQuery
method. The object will contain properties correspondent to each custom query "name", and the correspondent value will be the provided queryMaker
. This object is exposed for making easier the process of testing custom query methods.
Example
books.addQuery("ofAuthor", author => ({ urlParams: { author }}));
console.log(books.queryMethods.ofAuthor(2));
// { urlParams: { author: 2 }}