> For the complete documentation index, see [llms.txt](https://stash-it.gitbook.io/stash-it/llms.txt). Markdown versions of documentation pages are available by appending `.md` to page URLs; this page is available as [Markdown](https://stash-it.gitbook.io/stash-it/lifecycle-of-methods.md).

# 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):

```javascript
{
    // (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:

1. Given method is called with argument(s) passed to it.
2. `preData` is being fetched, which stands for: *get me data for `pre` lifecycle part of this method, using passed object*. Under the hood **stash-it** walks through all event handlers registered for `preMethodName` event:
   1. calls those handlers one by one
   2. first handler is called with that object passed as an argument
   3. returned value form each event handler is being passed to the next one (loop)
   4. returned data from the last event handler is returned as `preData`
3. Adapter's method is being called with `arg` returned by `getPreData` and returns its `result`.
4. `postData` is being fetched, which stands for: *get me data for `post` lifecycle 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 for `postMethodName` event:
   1. calls those handlers one by one
   2. first handler is called with that object passed as an argument
   3. returned value from each event handler is being passed to the next one (loop)
   4. returned data from the last event handler is returned as `postData`
5. `result` that came back from adapter and was passed through `getPostData` is being returned finally by this method. Bare in mind that `result` might 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:

```javascript
// 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;
    }
}
```

1. cache instance's [`getItem(key)`](/stash-it/api/cacheinstance/getitem-key.md) method is called, takes a `key` as an argument (depending on method used, there can be more arguments e.g. [setItem(key, value, \[extra\]](/stash-it/api/cacheinstance/setitem-key-value-extra.md))).
2. `preData` is 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;
   * `getPreData` will construct a full event name - here it will be `'preGetItem'` (camelCase'd); so, for `hasItem(key)` it will be `'preHasItem'` and so on;
   * object being passed contains properties for all arguments used in function called, here `key` only (for `setItem(key, value, [extra])` it will contain `key`, `value` and `extra`)
   * that object will **always contain** `cacheInstance` which is a reference to `this` which is cache instance itself; this is useful if any event handler will need to use any [cache instance's methods](/stash-it/api/cacheinstance.md) - 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 to `getPreData`), but values for those properties might be different.<br>

   *Why?*<br>

   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.
3. 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's `buildKey` method (hence `this.buildKey(preData.key)`,
   * key is being built using key value returned in `preData`, not key passed to `getItem` method.
4. `postData` is 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, or `removeItem(key)` will have `'removeItem'` passed;
   * `getPostData` will construct a full event name - here it will be `'postGetItem'` (camelCase'd); so, for `hasItem(key)` it will be `'postHasItem'` and so on;
   * object being passed contains properties for all arguments used in function called, here `key` only (for `setItem(key, value, [extra])` it will contain `key`, `value` and `extra`), **but also** item returned by adapter;
   * that object will **always contain** `cacheInstance` which is a reference to `this` which is cache instance itself; again, this is useful if any event handler will need to use any [cache instance's methods](/stash-it/api/cacheinstance.md);

   Returned `postData` (an object) will contain the very same properties (as ones passed initially to `getPostData`), but values for those properties might be different.<br>

   *Why?*<br>

   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 `getItem` method `postData` will have `key`, `item` and `cacheInstance` property. There can be additional properties added (by mentioned handlers), but those three will be there always.
5. Finally, `item` is returned, the one stored in `preData`, 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.
