Javascript 脱机时发生Firestore更改时未更新NGRX状态

Javascript 脱机时发生Firestore更改时未更新NGRX状态,javascript,firebase,google-cloud-firestore,ngrx,angularfire2,Javascript,Firebase,Google Cloud Firestore,Ngrx,Angularfire2,我有一个AngularFire应用程序,它使用AngularFire、NgRx和云Firestore作为db,在这里我启用了离线持久性 我的问题是,当我在脱机时更改文档时,effect函数不会触发成功操作,因为Firestore承诺在脱机时不会得到解决,而只有在请求到达服务器后才会得到解决 目前,我正努力寻找一种在离线时用本地数据更新存储的好方法 一种方法是在加载数据之前检查fromCache标志,这样如果fromCache为true(即,我们处于脱机状态),我就可以从本地数据库而不是存储区加载

我有一个AngularFire应用程序,它使用AngularFireNgRx云Firestore作为db,在这里我启用了
离线持久性

我的问题是,当我在脱机时更改文档时,effect函数不会触发成功操作,因为Firestore承诺在脱机时不会得到解决,而只有在请求到达服务器后才会得到解决

目前,我正努力寻找一种在离线时用本地数据更新存储的好方法

一种方法是在加载数据之前检查
fromCache
标志,这样如果fromCache为true(即,我们处于脱机状态),我就可以从本地数据库而不是存储区加载数据,但在我看来这是一个肮脏的解决方法

效果

//--- Effect triggered to load document in the home page ----
  firstSet$ = createEffect(() => {
    return this.actions$.pipe(
      ofType(PlacesActions.loadFirstPlaces),
      switchMap(() => {
        return this.placeService.getFirstSet().pipe(
          map((places) => {    
            return PlacesActions.loadFirstPlacesSuccess({ places });
          }),
          catchError((error) => of(PlacesActions.loadFirstPlacesFailure({ error }))),
          takeUntil(this.subService.unsubscribe$)
        );
      })
    );
  });


//--- Effect triggered when a document is updated ----
  updatePlace$ = createEffect(() => {
    return this.actions$.pipe(
      ofType(PlacesActions.updatePlace),
      concatMap((action) => {
        // ----- Below the NEW code, without promise ----
      try {
            this.placeService.savePlace(action.place);
            this.router.navigate(['/home']);
            return of(PlacesActions.updatePlaceSuccess({ place: action.place }));
          }
          catch(error) {
            return of(PlacesActions.updatePlaceFailure({ error }))
          }

        /*
        // ----- Below the old code ----
        return from(this.placeService.savePlace(action.place))
          .pipe(
            map((place: Place) => {
              this.router.navigate(['/home']);
              return PlacesActions.updatePlaceSuccess({ place });
            }),
            catchError((error) => of(PlacesActions.updatePlaceFailure({ error })))
          );
         */
        })
    );
  });
ngOnInit(): void {

    // Set the data from the store, if available there
    this.places$ = this.store.select(getAllPlaces).pipe(
      tap((data) => {
        this.places = data;            
      })
    );

   /*Dispatch load action to load data from the server or local cache.
     If I use the PROMISE approach for the update method,
     the data coming from the local cache has the old data.
     The edits done while offline are not provided.*/
   this.store.dispatch(loadFirstPlaces());
  }
DB服务

savePlace(place): void {
   this.firestoreRef.doc<Place>(`places/${place.id}`).update(place);
}

/* Old version of savePlace using Promise for the Update
async savePlace(place): Promise<void> {
    return await this.firestoreRef.doc<Place>(`places/${place.id}`).update(place);
}
*/

loadFirstPlaces(limit: number = 9,
                orderBy: OrderModel = { propName: 'modifiedOn', order: 'desc' }){

    const query = (ref: CollectionReference) => 
                   ref.orderBy(orderBy.propName, orderBy.order)
                      .limit(limit);

    return this.firestoreRef.collection<Place>('Places', query)
                            .valueChanges()
                            .pipe(shareReplay(1));
  }

update()
调用完成时,本地缓存已更新。因此,这也是更新应用程序状态的正确时机:

  async savePlace(place): Promise<void> {
      const result = this.firestoreRef.doc<T>(`places/${place.id}`).update(place)
      // TODO: update the state here
      return await result;
  }

如果本地写入操作失败,
update
将抛出一个异常,该异常将从
savePlace
转义,向调用者发出失败信号。

因此,解决方案是强制更新状态,忽略更新结果(成功/错误),因为这只有在它到达服务器时才能得到解决?这取决于目标:如果您想在UI中显示什么时候写入了服务器,请在侦听器中使用promise或
fromCache
/
pendingWrites
标志。如果您只关心写入本地缓存的更改,则不需要执行任何这些操作。API的设计目的是让这条路变得愉快。我的目标是为用户提供无缝体验,从而在脱机时立即显示本地更改。在引入NgRx之前,我确实展示了缓存中挂起的更改。现在有了提供数据的存储,我需要直接更新它,而不查看更新调用的结果,否则我就不会有状态的本地更改。然后,我将删除建议中的承诺,并将save方法调用封装在try/catch中。让我知道结果如何。我对NgRX没有特别的经验,因此可能缺少一些映射的细微差别。我将更新我的问题,以便您也可以获得缺少的相关部分。我面临的问题是,如果我使用更新方法的promise,那么从本地缓存中获取文档不会返回所做的更改(它会返回脱机更改的第一个文档,但不会返回第二个或第三个…)。同时感谢您的帮助:)
  savePlace(place): void {
      this.firestoreRef.doc<T>(`places/${place.id}`).update(place)
  }