永続的なストアとストレージ アイテムのキーのリストを備えた Angular アプリがあります。アプリの実行中に同期的にアクセスできるように、アプリの起動時に既知のキーの値を永続ストアからメモリに非同期的にロードしたいと考えています。そこで、Observable を作成しました。Observable は、キー リストのすべての要素を反復処理し、パイプをアタッチします。パイプは、各要素の値を取得し、キーと値の組み合わせを渡す必要があるため、それらをキャッシュに格納できます。永続ストレージで値が見つからない場合をキャッチする必要があります。残念ながら、これはキーの 1 つに対してのみ機能します。次に、外側の Observable が予期せず完了します。
ログを見ると、外側の Observable がキー リストの 3 つの要素を正しく反復し、switchMap() を実行していることがわかります。ただし、永続ストレージから値が 1 つだけ取り出され、最初の要素の localStorageService.get()-Observable が完了すると、from-Observable が完了します。
ログには次のように表示されます。
- from() $.next => (2) ["authorizationDataIdToken", 1]
- switchMap(): キー: authorizationDataIdToken
- from() $.next => (2) ["_isAuthorized", 0]
- switchMap(): キー: _isAuthorized
- from() $.next => (2) ["userData", 0]
- switchMap(): キー: userData
- from() $.complete
- localStorageService.get(userData) $.next => [オブジェクト オブジェクト]
- from() - switchMap の後 $.next => (2) ["userData", "[object Object]"]
- OIDC ストレージ: キャッシュ キー: userData、値: [オブジェクト オブジェクト]
- localStorageService.get(userData) $.complete
- from() - switchMap $.complete の後
- OIDC ストレージ: すぐに使用できます。
load-into-cache-function のコードは次のとおりです。
private prepareForUsage() {
// Take each element from the securely-stored-keys-list,
// get their values from the secured storage and put them into the cache.
from(Object.entries(this.keysStoredSecurely)).pipe(
log('from()'),
// At this point, we got the key and want to load the value from the local storage.
// But we want to have both, key and value afterwards.
switchMap(([key, protectionLevel]) => {
console.log('switchMap(): key: ', key);
// Here we try to fetch the value for the key via local storage service.
return this.localStorageService.get(key, true).pipe(
log(`localStorageService.get(${key})`),
// Because the item we want to access might not exist yet, we could get an error, that we want to catch.
catchError((error, _) => {
if (isDevMode()) { console.warn(`${error}, key: ${key}`); }
return of(undefined);
}),
// Here we have the value for the key and we want to combine both and return it.
map(value => [key, value])
);
}),
log('from() - after switchMap'),
).subscribe({
// Put each item in the cache.
next: ([key, value]) => {
if (key === undefined || value === undefined) {
if (isDevMode()) { console.log(`OIDC Storage: Key or value missing. key: ${key}, value: ${value}`); }
} else {
if (isDevMode()) { console.log(`OIDC Storage: Cache key: ${key}, value: ${value}`); }
sessionStorage.setItem(key, value);
}
},
error: (error) => {
if (isDevMode()) { console.error(`OIDC Storage: ${error}`); }
},
// Declare the storage as ready for usage.
complete: () => {
if (isDevMode()) { console.log('OIDC Storage: ready for use.'); }
this.isReadyForUsage.next(true);
}
});
}
これは、ローカル ストレージ サービスの get() 関数のシグネチャです。
get(key: string, encrypted: boolean = false): Observable<string>
from-Observable が発行するすべての要素に対してローカル ストレージ サービスの get() 関数の呼び出しが実行されることを期待していますが、一度しか呼び出されていないことがわかり、何が間違っていたのかわかりません。