Angular NGXS离子存储SQLite

Angular NGXS离子存储SQLite,angular,ngxs,Angular,Ngxs,我正在尝试在NGXS中实现SQLite。我正在使用此处定义的NGXS存储: 我定义了如下自定义存储引擎: @Injectable({ providedIn: 'root' }) export class IonicStorageProvider implements AsyncStorageEngine { constructor(private storage: Storage) {} length(): Observable<number> {

我正在尝试在NGXS中实现SQLite。我正在使用此处定义的NGXS存储:

我定义了如下自定义存储引擎:

@Injectable({
    providedIn: 'root'
})
export class IonicStorageProvider implements AsyncStorageEngine {
    constructor(private storage: Storage) {}

    length(): Observable<number> {
        return from(this.storage.keys()).lift(keyArray => keyArray.length);
    }

    getItem(key: any): Observable<any> {
        return from(this.storage.get(key));
    }

    setItem(key: any, val: any): Observable<any> {
        return from(this.storage.set( key, val ));
    }

    removeItem(key: any): Observable<any> {
        return from(this.storage.remove(key));
    }

    clear(): Observable<void> {
        return from(this.storage.clear());
    }

    key(val: number): Observable<string> {
        throw new Error('Method not implemented.');
    }

    keys(): Observable<any> {
        return from(this.storage.keys());
    }
}
并定义了实现句柄功能的StoragePlugin:

import { Injectable, Inject } from '@angular/core';
import { NgxsPlugin, NgxsNextPluginFn, actionMatcher, InitState, UpdateState, getValue, setValue } from '@ngxs/store';
import { tap, concatMap, reduce, map, flatMap } from 'rxjs/operators';
import { Observable, of, from, concat } from 'rxjs';
import {
    NGXS_STORAGE_PLUGIN_OPTIONS,
    STORAGE_ENGINE,
    NgxsStoragePluginOptions,
    StorageEngine,
    AsyncStorageEngine,
    AsyncStorageEngineProxy
} from '@ngxs-labs/async-storage-plugin';

@Injectable()
export class StoragePlugin implements NgxsPlugin {
    private asyncStorageEngine: AsyncStorageEngine;

    constructor(
        @Inject(NGXS_STORAGE_PLUGIN_OPTIONS) private pluginOptions: NgxsStoragePluginOptions,
        @Inject(STORAGE_ENGINE) private storageEngine: StorageEngine | AsyncStorageEngine
    ) {
        if (typeof this.storageEngine.length === 'function') {
            this.asyncStorageEngine = this.storageEngine as AsyncStorageEngine;
        } else {
            this.asyncStorageEngine = new AsyncStorageEngineProxy(this.storageEngine as StorageEngine);
        }
    }

    handle(state: any, event: any, next: NgxsNextPluginFn) {
        console.log('StoragePlugin handle');
        const options = this.pluginOptions || {} as any;
        const matches = actionMatcher(event);
        const isInitAction = matches(InitState) || matches(UpdateState);
        const keys: any[] = Array.isArray(options.key) ? options.key : [options.key];
        let hasMigration = false;
        let initAction: Observable<any> = of(state);

        if (isInitAction) {
            console.log('StoragePlugin getItem');
            initAction = from(keys).pipe(
                concatMap(key => this.asyncStorageEngine.getItem(key.key || key).pipe(map(val => [key, val]))),
                reduce((previousState, [key, val]) => {
                    console.log('StoragePlugin: getItem key:', key);
                    console.log('StoragePlugin: getItem val:', val);
                    const isMaster = key === '@@STATE';
                    let nextState = previousState;
                    if (val !== 'undefined' && typeof val !== 'undefined' && val !== null) {
                        try {
                            val = options.deserialize(val);
                        } catch (e) {
                            console.error('Error ocurred while deserializing the store value, falling back to empty object.', e);
                            val = {};
                        }

                        if (options.migrations) {
                            options.migrations.forEach(strategy => {
                                const versionMatch = strategy.version === getValue(val, strategy.versionKey || 'version');
                                const keyMatch = (!strategy.key && isMaster) || strategy.key === key;
                                if (versionMatch && keyMatch) {
                                    val = strategy.migrate(val);
                                    hasMigration = true;
                                }
                            });
                        }
                        if (!isMaster) {
                            nextState = setValue(previousState, key.key || key, val);
                        } else {
                            nextState = { ...previousState, ...val };
                        }
                    }
                    return nextState;
                }, state),
            );
        }

        return initAction.pipe(
            concatMap(stateAfterInit => next(stateAfterInit, event)),
            tap(async nextState => {
                if (!isInitAction || (isInitAction && hasMigration)) {
                    for (let key of keys) {
                        let val = nextState as any;

                        if (key !== '@@STATE') {
                            if (!key || typeof (key) === 'string') {
                                val = await getValue(nextState, key);
                            } else {
                                const subKeys = key.subKeys;
                                key = key.key;
                                val = await getValue(nextState, key);

                                const filtered = [];
                                for (const element of val) {
                                    const obj = {} as any;

                                    for (const subKey of subKeys) {
                                        obj[subKey] = element[subKey];
                                    }

                                    filtered.push(obj);
                                }

                                val = filtered;
                            }
                        }

                        try {
                            console.log('StoragePlugin: setItem key:', key);
                            console.log('StoragePlugin: setItem val:', val);
                            this.asyncStorageEngine.setItem(key, options.serialize(val));
                        } catch (e) {
                            console.error('Error ocurred while serializing the store value, value not updated.', e);
                        }
                    }
                }
            })
        );
    }
从'@angular/core'导入{Injectable,injection};
从'@ngxs/store'导入{NgxsPlugin、NgxsNextPluginFn、actionMatcher、InitState、UpdateState、getValue、setValue};
从“rxjs/operators”导入{tap,concatMap,reduce,map,flatMap};
从“rxjs”导入{可观察的,of,from,concat};
进口{
NGXS_存储_插件_选项,
存储引擎,
NGXS存储插件操作,
StorageEngine,
异步存储引擎,
AsyncStorageEngineProxy
}来自“@ngxs实验室/异步存储插件”;
@可注射()
导出类StoragePlugin实现NgxsPlugin{
专用asyncStorageEngine:asyncStorageEngine;
建造师(
@注入(NGXS_存储_插件_选项)专用插件操作:NGXS存储插件操作,
@注入(存储引擎)专用存储引擎:storageEngine | AsyncStorageEngine
) {
if(this.storageEngine.length的类型=='function'){
this.asyncStorageEngine=this.storageEngine作为asyncStorageEngine;
}否则{
this.asyncStorageEngine=新的AsyncStorageEngineProxy(this.storageEngine作为storageEngine);
}
}
句柄(状态:any,事件:any,下一个:NgxsNextPluginFn){
log('storagepluginhandle');
const options=this.pluginOptions | |{}如有;
const matches=actionMatcher(事件);
const isInitAction=matches(InitState)| | matches(UpdateState);
常量键:any[]=Array.isArray(options.key)?options.key:[options.key];
让hasmigation=false;
let initAction:Observable=of(状态);
如果(isInitAction){
log('StoragePlugin getItem');
initAction=来自(键)。管道(
concatMap(key=>this.asyncStorageEngine.getItem(key.key | | key).pipe(map(val=>[key,val])),
减少((以前的状态,[key,val])=>{
log('StoragePlugin:getItem key:',key);
log('StoragePlugin:getItem val:',val);
常量isMaster=key=='@@STATE';
设nextState=previousState;
if(val!='undefined'&&typeof val!='undefined'&&val!==null){
试一试{
val=选项。反序列化(val);
}捕获(e){
console.error('反序列化存储值时出错,返回空对象',e);
val={};
}
如果(选项.迁移){
options.migrations.forEach(策略=>{
const versionMatch=strategy.version==getValue(val,strategy.versionKey | | version');
const keyMatch=(!strategy.key&&isMaster)| | strategy.key==key;
if(versionMatch&&keyMatch){
val=strategy.migrate(val);
hasmigation=true;
}
});
}
如果(!isMaster){
nextState=setValue(上一个状态,key.key | | key,val);
}否则{
nextState={…previousState,…val};
}
}
返回下一状态;
},陈述),
);
}
返回initAction.pipe(
concatMap(stateAfterInit=>next(stateAfterInit,事件)),
点击(异步下一步状态=>{
if(!isInitAction | |(isInitAction&&hasmigation)){
对于(让钥匙中的钥匙){
设val=nextState,如有;
如果(键!='@@STATE'){
如果(!key | | typeof(key)=='string'){
val=等待获取值(nextState,key);
}否则{
const subKeys=key.subKeys;
key=key.key;
val=等待获取值(nextState,key);
常数过滤=[];
for(val的常量元素){
const obj={}如有;
for(子键的常量子键){
obj[subKey]=元素[subKey];
}
过滤推送(obj);
}
val=过滤;
}
}
试一试{
log('StoragePlugin:setItem key:',key);
log('StoragePlugin:setItem val:',val);
this.asyncStorageEngine.setItem(key,options.serialize(val));
}捕获(e){
console.error('序列化存储值时出错,值未更新',e);
}
}
}
})
);
}
我已经分别在存储上测试了get和set,它工作得很好。但是当启动应用程序时,它首先多次调用setItem重置状态,然后调用getItem(检索重置状态)

在此之前,我一直在使用一个名为getItem的localstorage插件,然后是名为setItem的插件,它可以正确设置状态

旧存储提供程序:

import { Observable, from } from 'rxjs';
import { AsyncStorageEngine } from '@ngxs-labs/async-storage-plugin';
import { Injectable } from '@angular/core';
import { Storage } from '@capacitor/core';
import { pluck } from 'rxjs/operators';

@Injectable({
    providedIn: 'root'
})
export class CapacitorStorageProvider implements AsyncStorageEngine {
    length(): Observable<number> {
        return from(Storage.keys()).lift(keyArray => keyArray.length);
    }

    getItem(key: any): Observable<any> {
        return from(Storage.get({ key: key })).pipe(pluck('value'));
    }

    setItem(key: any, val: any): Observable<any> {
        return from(Storage.set({ key: key, value: val }));
    }

    removeItem(key: any): Observable<any> {
        return from(Storage.remove({ key: key }));
    }

    clear(): Observable<void> {
        return from(Storage.clear());
    }

    key(val: number): Observable<string> {
        throw new Error('Method not implemented.');
    }
}
import{Observable,from}from'rxj
import { Observable, from } from 'rxjs';
import { AsyncStorageEngine } from '@ngxs-labs/async-storage-plugin';
import { Injectable } from '@angular/core';
import { Storage } from '@capacitor/core';
import { pluck } from 'rxjs/operators';

@Injectable({
    providedIn: 'root'
})
export class CapacitorStorageProvider implements AsyncStorageEngine {
    length(): Observable<number> {
        return from(Storage.keys()).lift(keyArray => keyArray.length);
    }

    getItem(key: any): Observable<any> {
        return from(Storage.get({ key: key })).pipe(pluck('value'));
    }

    setItem(key: any, val: any): Observable<any> {
        return from(Storage.set({ key: key, value: val }));
    }

    removeItem(key: any): Observable<any> {
        return from(Storage.remove({ key: key }));
    }

    clear(): Observable<void> {
        return from(Storage.clear());
    }

    key(val: number): Observable<string> {
        throw new Error('Method not implemented.');
    }
}