Coder Social home page Coder Social logo

vuex-cache's People

Contributors

cwilby avatar kierans avatar lukasbesch avatar qnp avatar rah-emil avatar superwf avatar vitorluizc avatar

Stargazers

 avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar

Watchers

 avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar

vuex-cache's Issues

Export StoreCache interface so that it can be mocked

In my Component tests, I want to mock/fake my Vuex Store and the cache property to make sure that my component is integrating with my actions correctly.

However because the StoreCache interface isn't exported I can't create a typesafe mock/fake.

store.cache.dispatch throws an error if payload have circular references

If you pass a payload with circular references to store.cache.dispatch it throws TypeError: Converting circular structure to JSON.

This can be checked by running the code below.

import Vue from 'vue';
import Vuex, { Store } from 'vuex';
import cache from 'vuex-cache';

Vue.use(Vuex);

const store = new Store({
  plugins: [
    cache({})
  ],
  actions: {
    show(_, value) {
      console.log(value);
    }
  }
});

const a = {}, b = {};

a.b = b;
b.a = a;

store.cache.dispatch('show', a); // It throws an error.

See by yourself on CodeSandbox.

@superwf vuex-cache uses JSON.stringify and it carries its limitations. So I propose fallback to uncached action instead of just throws Error.

Caching is not taking place in namespaced environment

Hi,

I'm testing this plugin. However it does not seem to be working.

app.js

import Vue from 'vue'
import Vuex from 'vuex'
import vuexCache from 'vuex-cache'

Vue.use(Vuex)

// Load store modules dynamically.
const requireContext = require.context('./modules', false, /.*\.js$/)

const modules = requireContext.keys()
  .map(file =>
    [file.replace(/(^.\/)|(\.js$)/g, ''), requireContext(file)]
  )
  .reduce((modules, [name, module]) => {
    if (module.namespaced === undefined) {
      module.namespaced = true
    }

    return { ...modules, [name]: module }
  }, {})

export default new Vuex.Store({
  plugins: [vuexCache],
  modules
})

modules/exchange.js

import Trade from '~/api/trade.js'
import * as types from '../mutation-types'

// state
export const state = {
  exchanges: null,
  symbols: null
}

// getters
export const getters = {
  exchanges: state => state.exchanges
}

// mutations
export const mutations = {
  [types.SET_EXCHANGES] (state, { data }) {
    state.exchanges = data
  },

  [types.SET_SYMBOLS] (state, { data }) {
    state.symbols = data
  }
}

// actions
export const actions = {
  getExchanges ({ commit, dispatch }) {
    return Trade.getExchanges()
      .then(exchanges => {
        commit(types.SET_EXCHANGES, exchanges)
      })
      .catch(error => console.log(error))
  },

  getSymbols ({ commit, dispatch }) {
    return Trade.getSymbols()
      .then(symbols => {
        commit(types.SET_SYMBOLS, symbols)
      })
      .catch(error => console.log(error))
  }
}

And in the component I have this

  created () {
    if (this.$store.cache.has('exchange/getExchanges')) {
      console.log('cached')
    }

    this.$store.cache.dispatch('exchange/getExchanges')
      .then(() => {
        console.log(this.exchange.exchanges)
      })

    this.$store.cache.dispatch('exchange/getSymbols')
      .then(() => {
        console.log(this.exchange.symbols)
      })
  }

I expect the console to output cached and I also expect the actions not to happen at each load, however both fail.

How can I solve this?

FEATURE: Set default timeout value

I like the new timeout feature. It would be nice if we could set a default timeout while still being able to give a timeout per dispatch as well. Perhaps it could be passed into the constructor when the plugin is initialized:

import Vuex from 'vuex'
import vuexCache from 'vuex-cache'
const store = new Vuex.Store({
  state: {
    ...
  },

  plugins: [vuexCache(DEFAULT_TIMEOUT_VALUE_HERE)],

  mutations: {
    ...
  },

  actions: {
    ...
  }
})

Exclude Timeout Setting From Cache Key Name

When passing a timeout value in the Vuex call like so:

await this.$store.cache.dispatch('customer/getInfo', {
    timeout: SettingsConstants.longCacheTimeout
})

It looks like it is adding the timeout value to the name of the cache key. So after making that call and then running this.$store.cache.entries(), I see that the cache entry name is set to:

customer/getInfo:{"timeout":21600000}

This is kind of annoying because now I will have to pass the timeout value to all calls, such as .has() and .delete().

For example, the following would not find or delete the cache key (which was unexpected):

this.$store.cache.has('customer/getInfo')
this.$store.cache.delete('customer/getInfo')

So I would have to do this instead:

this.cache.has('customer/getInfo', {
    timeout: SettingsConstants.longCacheTimeout
})

this.cache.delete('customer/getInfo', {
    timeout: SettingsConstants.longCacheTimeout
})

Could the settings object be excluded from the cache key name while still including the Vuex params in the name? Thanks.

how to use vuex-cache for axios action

If the action return a promise in which there is an axios request (post or get), how to use vuex-cache?
I made commit(response.data) within axios response.

I tried, but the content within cache is promise. Though there is no other network request for the second time request, but the result is not correct.

2019-1-11 15-47-02

Unexpected keyword 'const' - Babel Error?

Receiving the following error on an iOS 9.3.2 device when using this plugin:

Unexpected keyword 'const'. Const declarations are not supported in strict mode.

I assume it has to do with babel 7 configuration (as old Safari versions do not natively handle const). So would this be something we need to handle in then config of our project or is this something wrong in the plugin code? If so, any tips to help me accomplish that? I am lost when it comes to webpack and babel configs. Thanks!

create a mapCacheActions helper

Would be nice to have a helper function similar to mapActions, but for our cache actions.

import types from '@/store/types';
import { mapCacheActions } from 'vuex-cache';

export default {
  ...,
  methods: mapCacheActions({
    fetchUser: 'user/FETCH',
    fetchServices: { type: 'service/FETCH', timeout: 5000, param: 'ACTIVE' }
  }),
  mounted () {
    this.fetchUser();
    this.fetchServices();
  }
};

mapCacheActions should resolve it's arguments

mapCacheActions({ A: 'ACTION' }) === ({
  A () {
    return this.$store.cache.dispatch('ACTION');
  }
})

mapCacheActions({ B: { type: 'ACTION', timeout: 200, param: '0' } }) === ({
  B () {
    return this.$store.cache.dispatch({ type: 'ACTION', timeout: 200, param: '0' });
  }
})

store.cache.dispatch treat falsy values as undefined

The argsToString function ignore falsy values.

vuex-cache/src/index.js

Lines 10 to 12 in 637815b

if (args[1]) {
type = `${type}:${toString(args[1])}`
}

We shouldn't ignore any value, even undefined should be used to generate cache's key.

This can be checked by running the code below.

import Vue from 'vue';
import Vuex, { Store } from 'vuex';
import cache from 'vuex-cache';

Vue.use(Vuex);

const store = new Store({
  plugins: [
    cache({})
  ],
  actions: {
    hi(_, payload) {
      console.log('Hi', payload);
    }
  }
});

store.cache.dispatch('hi', undefined); // It shows 'Hi undefined'

store.cache.dispatch('hi', null); // It don't show anything

store.cache.dispatch('hi', 0); // It don't show anything

store.cache.dispatch('hi', ''); // It don't show anything

store.cache.dispatch('hi', NaN); // It don't show anything

store.cache.dispatch('hi', false); // It don't show anything

See by yourself on CodeSandbox.

cache.dispatch , Promise and return response

I'm following the docs

import { cacheAction } from 'vuex-cache';

// ...

const actions = {
  'FETCH_STARGAZERS': cacheAction(
    ({ cache, commit }, payload) => (
      cache.dispatch('FETCH_REPOSITORIES')
        .then((repos) => Promise.all(repos.map(getStargazers)))
        .then((stargazers) => {
          commit('STARGAZERS', [].concat(...stargazers));
        })
    )
  ),

  'SET_STARGAZERS': (context, payload) => { ... }
}

I have the followings (my code)

FETCH_LISTINGSV2_CACHED: cacheAction(function({ cache, dispatch, commit }, id) {
    console.info('FETCH_LISTINGSV2_CACHED', id)
    cache.dispatch('GET_LISTINGV2', id)
  }),
async GET_LISTINGV2({ commit }, id) {
    const response = await this.$axios.get('/listings/' + id, {
      baseURL: `https://${APISERVERS[Math.floor(Math.random() * APISERVERS.length)]}/api/v1`,
      headers: headers
    })
    const { listing } = await response
    return listing
  },

It works, but now I wish to do the following:

  • use the 'data' (response) from the either 'FETCH_LISTINGSV2_CACHED' or 'GET_LISTINGV2
    and 'commit' it to the store.
  • the 'data' (response) is the 'json' response from my RETS service.
  • my commits are working (tested) regardless of 'vuex-cache'

I just could not get the 'syntax' on how to use 'Promise.all, map' to work for me.

vuex-cache with Nuxt.js

How might one go about using vuex-cache with Nuxt.js?

The way the Vuex store works with Nuxt doesn't support a way to use the plugins: [vuexCache] syntax, so I was wondering if there might be an alternate way to instantiate vuex-cache with the store?

A similar plugin (vuex-persistedstate) has this as a solution:

// nuxt.config.js

...
plugins: [{ src: '~/plugins/localStorage.js', ssr: false }]
...
// ~/plugins/localStorage.js

import createPersistedState from 'vuex-persistedstate'

export default ({store}) => {
  window.onNuxtReady(() => {
    createPersistedState({
        key: 'yourkey',
        paths: [...]
        ...
    })(store)
  })
}

Perhaps a similar method might work for vuex-cache?

TTL for cached items

It could be a great feature to have some kind of configuration for all cache actions.
We could pass to the cache.dispatch an options objeto which may have a ttl (seconds or something else) that will clear that cached item after some configurable time.
This would avoid the delete of all cached items.

I'll try to do it and then I'll make a pill request as soon as I can.

Thanks for the plug-in ;)

Use with Store Module

I have a store module named 'cache', like so:

import cache from '@/modules/cache/_store';
export default new Vuex.Store({
    modules: {
        cache,
    },
    strict: true,
});

But using this.$store.cache.dispatch('cache/doSomething'); from within a component throws a "TypeError: this.$store.cache is undefined"

Originally posted by @bradley-varol in #9 (comment)

Default timeout does not work in createAction

When default timeout is defined in:

const store = new Vuex.Store({
    plugins: [createCache({timeout: 15000})],
    modules: {
            mystore: MyStore,
   }

and then you have createAction used in a module

const MyStore = { 
    namespaced: true,
    actions: {
    "loadCached": cacheAction(async ({ cache }) => {
            cache.dispatch('load');
        }),
    }
}

With this combination when called store.cache.dispatch('MyStore/loadCached') it will never timeout as cacheAction uses own timeout options and not default one. With this combination you always need to define timeout to cacheAction as well.

Delete cache on call native dispatch

Should a native action call (e.g. without .cache) update an already existing cache? Or is the sequence below intended?

let users = ['Sven', 'Kurt']
store.dispatch('setUsers', users)
store.cache.dispatch('getUsers') // ['Sven', 'Kurt'] (not cached)
users.push('Nisse')
store.dispatch('setUsers', users)
store.dispatch('getUsers') // ['Sven', 'Kurt', 'Nisse'] (native action, not cached)
store.cache.dispatch('getUsers') // ['Sven', 'Kurt'] (cached)

Remove peerDependencies

I'm using Vuex 3 for a while with vuex-cache and today I realize vuex-cache is warning about incorrect peer depedency.

warning " > [email protected]" has incorrect peer dependency "vuex@^2.2.1".

Adding 3.x to peerDependencies would solve it, because 3.0 doesn't break plugins and dispatch APIs, but looking at Vuex 1 docs you can also notice plugins and dispatch APIs are same too. So, vuex-cache is compatible with all vuex versions and there's no reason to keep a peerDependencies checking it.

I'm just ignoring Vuex 0.x...

Persist cache

Are there any plans on adding the option to persist the cached data?

I want to keep the cached data within a browser session (including page reloads). I thought about combining this plugin with vuex-persistedstate to get the expected behaviour. Unfortunately I found out that the cache data is not stored in the module's state, so it doesn't work as expected.

Are there any plans on making this plugin compatible with other plugins by offering an interface to load an initial state, ..? Or even better implementing a persistence option in this plugin?

Thanks in advance.

Also cache requests with parameters

Hello I have a feature request for vuex-cache

An idea to cache also the requests with parameters?

'use strict';

var index = (function (store) {
  store.cache = new Map();

  store.cache.dispatch = function () {
    var type = arguments[0];
    if (arguments[1]) {
      type = type + JSON.stringify(arguments[1]);
    }
    if (!store.cache.has(type)) {
      store.cache.set(type, store.dispatch.apply(store, arguments));
    }
    return store.cache.get(type);
  };
});

module.exports = index;

[ASK] How to call cache on nuxtjs store module?

Hi, thank you for creating this plugin.

I made vuex-cache as plugin on NuxtJS and successfully call it on pages as mention in documentation , call store.cache.dispatch in fetch method to initiate cache of ajax call.

I think I need to call cache on store module actions,

I have this sample store module on NuxtJS

// store module for User Interface
export const state = () => ({
  snackbar: false,
  snackbarText: '',
  snackbarColor: 'secondary',
  snackTimeout: 4000
})

// mutations defined as object
export const mutations = {
  setState(state, params) {
    const keys = Object.keys(params)
    keys.forEach(key => (state[key] = params[key]))
  }
}
export const actions = {
  showAlert({ commit }, params) {
    commit('setState', {
      snackbar: true,
      snackbarText: params.msg,
      snackTimeout: params.timeout > 0 ? params.timeout : 4000,
      snackbarColor: params.color !== '' ? params.color : 'secondary'
    })
  },
 
  // I hope there is `cache` object
  getUUID({ cache, dispatch, commit, state }) {
    this.$axios.setHeader('Authorization', 'Bearer ' + state.accKey)
    return this.$axios.$get('/jsonapi').catch(() => {
      const alertMsg = {
        msg: 'Get UUID failed'
      }
      dispatch('showAlert', alertMsg)
    })
  },
  async doLogin({ cache, commit }) {
     // an axios call
     ....
    commit('setState', {
      isLogin: true,
      uuid: 'sample-uuid-string',
    })
    ....
    // I hope I can do this in the store action
    cache({timeout: 60000}).dispatch('showAlert', alertMsg)
  },
  async doLogout({ commit }) {
    commit('setState', {
      isLogin: false,
      uuid: '',
    })
     // I hope I can do this in the store action
     cache.clear()
   },
 }

How I can call cache on store module itself ?

Android 4.4.2 Map is not defined error

Using the latest version of the library, I receive the following error on an Android 4.4.2 WebView. Wondering if this was caused by recent changes to babel configs (#23)?

Uncaught ReferenceError: Map is not defined

Should we dismiss action errors?

Cache promise rejections is a common question (#7, #16), and I believe we need to discuss if we need cache actions errors or dismiss them?

Pros

  • Handle vue-cache rejections on our stores is undesirable behavior;
  • It'll cause some errors if is not well handled;
  • Users don't know about cache rejections, because is not documented anywhere;

Cons

  • It can add complexity and increase module size;
  • Intercepting the promise is an invasive procedure;

When dispatching `this` not bound correctly

This issue relates to #41 as I'm wanting to mock/fake the StoreCache for Component tests.

When dispatching (see vuex-cache.js#L297, #L305) this is bound to the store not the store cache. Given the cache.dispatch method doesn't use this, this bug probably hasn't surfaced yet. However when mocking/faking store.cache the cache methods are being called with the wrong this.

Documentation

Hi superwf,

I think this is a great package and would like to help a bit with the README to make it clearer and easier to read.

Would you accept a pull request for this?

Cheers!

cache.dispatch use async/await

cache.dispatch = async (...args) => {
    const type = argsToString(args)

    const timeout = getTimeout(args, option)
    if (timeout) {
      const now = Date.now()
      if (!timeoutCache.has(type)) {
        timeoutCache.set(type, now)
      } else {
        const timeoutOfCurrentType = timeoutCache.get(type)
        // console.log(now - timeout, timeoutOfCurrentType)
        if (now - timeout > timeoutOfCurrentType) {
          cache.delete(type)
          timeoutCache.delete(type)
        }
      }
    }

    if (!cache.has(type)) {
      cache.set(type, await store.dispatch.apply(store, args))
    }

cache.dispatch 使用async/await,当dispatch报错时不set cache?

store.cache.has returns `true` for expired actions

The cache's method has returns true for expired actions. For me it should return false because the cache will be ignored, so is like it was not there.

This can be checked by running the code below.

import Vue from 'vue';
import Vuex, { Store } from 'vuex';
import cache from 'vuex-cache';

Vue.use(Vuex);

const store = new Store({
  plugins: [
    cache({ timeout: 10000 })
  ],
  actions: {
    hi () {
      console.log('Hi');
    }
  }
});

store.cache.dispatch('hi'); // It shows 'Hi'

store.cache.dispatch('hi'); // It don't show anything

setTimeout(() => {
  store.cache.has('hi'); // It returns `true`, but the action is already expired

  store.cache.dispatch('hi'); // It shows 'Hi'
}, 10000);

See by yourself on CodeSandbox.

Webpack build error

Each time i run a production build, the build fails on Vue-cache module with this error.
UglifyJs Unexpected token: operator (>) [./node_modules/vuex-cache/index.module.js:1,0][app.js:43610,17]

'Dispatch' undefined when inside new Nuxt fetch()

In Nuxt 2.12+, there's a new fetch() method.

Example:

<script>
export default {
  async fetch() {
    await this.$store.cache.dispatch('getUser');
  },
};
</script>

Results in:

 ERROR  Error in fetch(): Cannot read property 'dispatch' of undefined

at VueComponent.fetch (server.js:6668:29)
at VueComponent.serverPrefetch (server.js:2515:31)
at waitForServerPrefetch (node_modules/vue-server-renderer/build.dev.js:8276:34)
at renderComponentInner (node_modules/vue-server-renderer/build.dev.js:8426:3)
at renderComponent (node_modules/vue-server-renderer/build.dev.js:8383:5)
at RenderContext.renderNode (node_modules/vue-server-renderer/build.dev.js:8294:5)
at RenderContext.next (node_modules/vue-server-renderer/build.dev.js:2598:23)
at cachedWrite (node_modules/vue-server-renderer/build.dev.js:2451:9)
at renderElement (node_modules/vue-server-renderer/build.dev.js:8544:5)
at renderNode (node_modules/vue-server-renderer/build.dev.js:8296:5)

My vuex-cache.js in ~/plugins:

import createVuexCache from 'vuex-cache';

export default ({ store, isHMR }) => {
  if (process.browser) {
    if (isHMR) {
      return;
    }

    const options = {
      timeout: 2 * 60 * 60 * 1000, // Equal to 2 hours in milliseconds.
    };

    const setupVuexCache = createVuexCache(options);
    window.onNuxtReady(() => setupVuexCache(store));
  }
};

I assume it's just because it is attempting to dispatch server-side but vuex-cache hasn't attached itself yet correctly to the $store instance.

Not sure if there's a solution to ensure that all dispatches server-side bypass the cache, and all client-side navigations include the cache action - barring doing twice the dispatch calls wrapped within if (process.browser) { checks?

Cache expiry

Just a suggestion,

Would be great if there was a way to set an expiry on the cache (ie 5 mins etc).

Something like store.cache.dispatch('LIST', 5 * 60, {..additional args}) etc

I can see where there might be issues keeping track of if additional arguments are expiries or normal data, but just off the top of my head:

 store.cache.dispatch = function () {
    const type = arguments[0]

    let current = store.cache.get(type)
    let now = new Date();    

    if (!store.cache.has(type) || current.expiry < now) {
      // Somehow add the expiry with expiry = now.setSeconds(now.getSeconds + arguments[1]) then splice it from the arguments?
      store.cache.set(type, store.dispatch.apply(store, arguments))
    }

    return store.cache.get(type)
  }

Recommend Projects

  • React photo React

    A declarative, efficient, and flexible JavaScript library for building user interfaces.

  • Vue.js photo Vue.js

    🖖 Vue.js is a progressive, incrementally-adoptable JavaScript framework for building UI on the web.

  • Typescript photo Typescript

    TypeScript is a superset of JavaScript that compiles to clean JavaScript output.

  • TensorFlow photo TensorFlow

    An Open Source Machine Learning Framework for Everyone

  • Django photo Django

    The Web framework for perfectionists with deadlines.

  • D3 photo D3

    Bring data to life with SVG, Canvas and HTML. 📊📈🎉

Recommend Topics

  • javascript

    JavaScript (JS) is a lightweight interpreted programming language with first-class functions.

  • web

    Some thing interesting about web. New door for the world.

  • server

    A server is a program made to process requests and deliver data to clients.

  • Machine learning

    Machine learning is a way of modeling and interpreting data that allows a piece of software to respond intelligently.

  • Game

    Some thing interesting about game, make everyone happy.

Recommend Org

  • Facebook photo Facebook

    We are working to build community through open source technology. NB: members must have two-factor auth.

  • Microsoft photo Microsoft

    Open source projects and samples from Microsoft.

  • Google photo Google

    Google ❤️ Open Source for everyone.

  • D3 photo D3

    Data-Driven Documents codes.