0

永続的なストアとストレージ アイテムのキーのリストを備えた 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() 関数の呼び出しが実行されることを期待していますが、一度しか呼び出されていないことがわかり、何が間違っていたのかわかりません。

4

1 に答える 1