Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

能不能把插件持久化的改为indexed DB #214

Closed
3 tasks done
suzhenghui-sky opened this issue Jun 20, 2023 · 5 comments
Closed
3 tasks done

能不能把插件持久化的改为indexed DB #214

suzhenghui-sky opened this issue Jun 20, 2023 · 5 comments
Labels
✨ enhancement New feature or request

Comments

@suzhenghui-sky
Copy link

Clear and concise description of the problem

因为我的程序要打包成APP放在手机上使用的,而手机会很经常清理掉本地存储的。但是indexed DB就没有这个问题。

Suggested solution

改为使用indexed DB作为持久化

Alternative

No response

Additional context

No response

Validations

@suzhenghui-sky suzhenghui-sky added the ✨ enhancement New feature or request label Jun 20, 2023
@Lixuhuilll
Copy link

可是,这个插件支持任意的具有getItem: (key: string) => string | null 和 setItem: (key: string, value: string) => void的对象作为storage,自行把indexed DB的相关操作封装到一个符合条件的对象里,将这个对象作为storage即可

@suzhenghui-sky
Copy link
Author

可是,这个插件支持任意的具有getItem: (key: string) => string | null 和 setItem: (key: string, value: string) => void的对象作为storage,自行把indexed DB的相关操作封装到一个符合条件的对象里,将这个对象作为storage即可

没看懂!能举一个简单的例子嘛?

@kagaricyan
Copy link

kagaricyan commented Jun 25, 2023

可是,这个插件支持任意的具有getItem: (key: string) => string | null 和 setItem: (key: string, value: string) => void的对象作为storage,自行把indexed DB的相关操作封装到一个符合条件的对象里,将这个对象作为storage即可

没看懂!能举一个简单的例子嘛?

我自己写了个,用的localforage。能用但感觉不太完美。
store.js


const pinia = createPinia();

// 手动恢复store
async function recoverStore() {
  // 把所有的store都拿过来
  const stores = [
    useStoreA(pinia),
    useStoreB(pinia),
    // ...
  ];

  // 遍历store恢复state
  stores.foreach(async store => {
    // 你自己的异步获取逻辑
    const data = await asyncGet(store.$id);
    store.$state = data;
  });
}



pinia.use(context => {
  // 使用插件时先恢复一下,不然会把空的store存起来
  recoverStore();

  context.store.$subscribe(async () => {
    // 你自己的异步保存逻辑
    await asyncStore(key, context.store.$state);
  });
});

main.js

(async function () {
  // 恢复完再创建vue
  await recoverStore();

  new Vue({
    pinia,
  });
})();

因为是异步存取,main.js中先调用recoverStore保证页面出来后能直接拿到缓存的数据;同时在pinia.use中,不调recoverStore会把初始状态存起来。可能跟导入先后顺序也有关系,所以两个地方都写了。

问题就在于是异步的,理论上如果修改完state后马上再读,可能还没来得及保存完就从缓存中读数据,此时读到的数据是旧的。
是不是应该把所以的action也包一下? :

pinia.use(context => {
    // 使用插件时先恢复一下,不然subscribe会把空的store存起来
  recoverStore(); 
  
  // 订阅state改变
  context.store.$subscribe(async () => {
    // 你自己的异步保存逻辑
    await asyncStore(key, context.store.$state);
  });

  // 把action包一层
  context.options.actions.forEach(action => {
    context.options.actions[action] = async () => {
      // 原本的action
      await action();
      // 执行完action后保存一次state,再进行后续操作
      await asyncStore(context.store.$is, context.store.$state);
    };
  });
});

@prazdevs
Copy link
Owner

I think the answer above solves the issue.
Keep in mind IndexedDB access is asynchronous, while the plugin needs a synchronous storage ☺️

@suzhenghui-sky
Copy link
Author

好的,多谢了。

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
✨ enhancement New feature or request
Projects
None yet
Development

No branches or pull requests

4 participants