Lifecycle of methods
You will learn what `pre...` and `post...` events are. Knowing this will help understand how plugins work and how to write them.
What are they and how do they work
Methods, available after creating an instance of cache: buildKey, getItem, getExtra, setExtra, addExtra, hasItem, setItem and removeItem, have certain lifecycle.
This is how it looks like from the inside (for any method):
{
// (1)
method(arg) {
// (2)
const preData = getPreData('methodName', { arg, cacheInstance: this });
// (3)
const result = adapter.method(preData.arg);
// (4)
const postData = getPostData('methodName', { arg: preData.arg, result, cacheInstance: preData.cacheInstance });
// (5)
return postData.result;
}
}Here's what is happening:
Given method is called with argument(s) passed to it.
preDatais being fetched, which stands for: get me data forprelifecycle part of this method, using passed object. Under the hood stash-it walks through all event handlers registered forpreMethodNameevent:calls those handlers one by one
first handler is called with that object passed as an argument
returned value form each event handler is being passed to the next one (loop)
returned data from the last event handler is returned as
preData
Adapter's method is being called with
argreturned bygetPreDataand returns itsresult.postDatais being fetched, which stands for: get me data forpostlifecycle part for this method, using passed object containing additionally the result returned from adapter. Under the hood stash-it walks through all event handlers registered forpostMethodNameevent:calls those handlers one by one
first handler is called with that object passed as an argument
returned value from each event handler is being passed to the next one (loop)
returned data from the last event handler is returned as
postData
resultthat came back from adapter and was passed throughgetPostDatais being returned finally by this method. Bare in mind thatresultmight be different after getting through all event handlers.
When you look at it, you most probably think middlewares - yes, it works in similar fashion.
Now, let's use getItem method and inspect this in more detail:
// this is an instance of cache
{
// (1)
getItem(key) {
// (2)
const preData = getPreData('getItem', { cacheInstance: this, key });
// (3)
const item = adapter.getItem(this.buildKey(preData.key));
// (4)
const postData = getPostData('getItem', { cacheInstance: preData.cacheInstance, key: preData.key, item });
// (5)
return postData.item;
}
}cache instance's
getItem(key)method is called, takes akeyas an argument (depending on method used, there can be more arguments e.g. setItem(key, value, [extra])).preDatais fetched. There are few things to remember, as there is a pattern here:all methods (buildKey, getItem, setItem, ... ones mentioned at the top of this page) have event name passed as a string of value equal to that method's name. So, for example
hasItem(key)method will have'hasItem'string passed,removeItem(key)will have'removeItem'passed, and so on;getPreDatawill construct a full event name - here it will be'preGetItem'(camelCase'd); so, forhasItem(key)it will be'preHasItem'and so on;object being passed contains properties for all arguments used in function called, here
keyonly (forsetItem(key, value, [extra])it will containkey,valueandextra)that object will always contain
cacheInstancewhich is a reference tothiswhich is cache instance itself; this is useful if any event handler will need to use any cache instance's methods - be careful with that, as it gives you much power, so be responsible;
Returned
preData(an object) will contain the very same properties (as ones passed initially togetPreData), but values for those properties might be different.Why?
If there are hooks added for given event (here
'preGetItem') and handlers (for those events) mutate the data (e.g. add prefix for the key or something else), then that mutated data is returned. If there are no hooks added for that event, data is returned without any changes.Adapter's method is being called, fetching item from storage. There are few things to mention here:
for all methods (except for
buildKey) key is being built using cache'sbuildKeymethod (hencethis.buildKey(preData.key),key is being built using key value returned in
preData, not key passed togetItemmethod.
postDatais fetched. There are few things to remember, as there is a pattern here as well:all methods (ones mentioned at the beginning) have event name passed as a string of value equal to that method's name. So, for example
hasItem(key)method will have'hasItem'string passed, orremoveItem(key)will have'removeItem'passed;getPostDatawill construct a full event name - here it will be'postGetItem'(camelCase'd); so, forhasItem(key)it will be'postHasItem'and so on;object being passed contains properties for all arguments used in function called, here
keyonly (forsetItem(key, value, [extra])it will containkey,valueandextra), but also item returned by adapter;that object will always contain
cacheInstancewhich is a reference tothiswhich is cache instance itself; again, this is useful if any event handler will need to use any cache instance's methods;
Returned
postData(an object) will contain the very same properties (as ones passed initially togetPostData), but values for those properties might be different.Why?
Similar to
preGetItem. If there are hooks added for given event (here'postGetItem') and handlers (for those events) mutate the data (e.g. increment counter how many times item was fetched from cache), then that mutated data is returned. If there are no hooks added for that event, data is returned without any changes.So, here, for
getItemmethodpostDatawill havekey,itemandcacheInstanceproperty. There can be additional properties added (by mentioned handlers), but those three will be there always.Finally,
itemis returned, the one stored inpreData, not the one returned directly by adapter.
And that's it.
Each method has its lifecycle described and all arguments that are passed by are mentioned as well.
Last updated