Angular NGXS离子存储SQLite
我正在尝试在NGXS中实现SQLite。我正在使用此处定义的NGXS存储: 我定义了如下自定义存储引擎: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> {
@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.');
}
}