Je suis en train de mettre en place un effect
dans une application utilisant NgRx
.
Pendant l'effet, j'ai besoin d'obtenir des valeurs de stockage, d'exécuter une certaine logique, puis de distribuer une ou plusieurs actions à la suite de la logique exécutée.
Donc, pour faciliter les choses, j'utilise un effet avec dispatch: false
.
public getCachedOrServerValue$ = createEffect(() =>
this.actions$.pipe(
ofType(myActions.getCachedOrServerValue),
switchMap((_) => this.getCachedOrServerValue())
), { dispatch: false }
);
Donc, dans l'exemple ci-dessus, je vais appeler getCachedOrServerValue
. Je veux utiliser switchMap
(plutôt que simplement tap
) donc si je reçois un nouveau myActions.getCachedOrServerValue
avant que le précédent ne soit terminé, il annulera l'abonnement précédent (d'après ce que je comprends de switchMap).
La fonction que nous appelons ressemble à ce qui suit...
private getCachedOrServerValue(): Observable<void> {
const result$ = new Observable<void>(async (subscriber) => { // <---- I need this to be async so I can use await
// First see if we can get it from the store
const cached = await this.storeUtils.getStoreValue(fromApp.getValue);
if (cached) {
this.store$.dispatch(myActions.getCachedOrServerValueSuccess(cached));
subscriber.next();
return;
}
// Need to request from the server
const name = await this.storeUtils.getStoreValue(fromApp.getSiteName);
// storeUtils.getStoreValue is just a helper we have to get a single value as a Promise
const valueId = await this.storeUtils.getStoreValue(fromApp.getValueId);
const serverValue = await this.myService.getValue(namevalueId);
this.store$.dispatch(myActions.storeValue(serverValue));
this.store$.dispatch(myActions.getCachedOrServerValueSuccess(cached));
});
return result$;
}
Tout d'abord, j'intègre un observable, car d'après ce dont je me souviens, nous avons besoin d'un observable pour utiliser cet appel au sein de switchMap
Deuxièmement (mon problème réel), je veux pouvoir utiliser await
à l'intérieur de l'Observable subscriber
argument de constructeur, mais VSCode rapporte une erreur...
Détails des erreurs...
L'argument de type '(this : Observable, subscriber : Subscriber) => Promise' n'est pas affectable au paramètre de type '(this : Observable, subscriber : Subscriber) => TeardownLogic'. Le type 'Promise' n'est pas assignable au type 'TeardownLogic'. La propriété 'unsubscribe' est manquante dans le type 'Promise' mais obligatoire dans le type 'Unsubscribable'.ts(2345)
types.d.ts(31, 5) : 'unsubscribe' est déclaré ici.
Quelqu'un a-t-il une idée de ce qu'est le problème ici, et comment je peux utiliser la aysnc/await
comme indiqué ci-dessus ?
Merci d'avance
UPDATE
D'après la réponse de @StPaulis, je peux éviter d'avoir à le faire (du moins dans cette situation).
Je peux le faire comme suit (pas encore testé, mais je suis sûr que ça ira) ....
public getCachedOrServerValue$ = createEffect(() =>
this.actions$.pipe(
ofType(myActions.getCachedOrServerValue),
switchMap(_ => from(this.getCachedOrServerValue()).pipe( // <-- use a from here
map(data => myActions.getCachedOrServerValueSuccess(data)),
catchError(error => of(myActions.getCachedOrServerValueFail(error)))
))));
private async getCachedOrServerValue(): Promise<DataState>{
// First see if we can get it from the store
const cached = await this.storeUtils.getStoreValue(fromApp.getValue);
if (cached) {
return cached;
}
// Need to request from the server
const name = await this.storeUtils.getStoreValue(fromApp.getName);
const valueId = await this.storeUtils.getStoreValue(fromApp.getValueId);
const serverValue = await this.myService.getValue(name, valueId);
return serverValue;
}