Angular8 RXJS CanDeactivate дождаться результата наблюдаемого перед деактивацией

Я пытаюсь использовать защиту CanDeactivate, чтобы определить, когда пользователь уходит от компонента. Цель состоит в том, чтобы # 1 проверить, владеет ли текущий пользователь блокировкой "Редактируется" для записи, и # 2, если да, вызвать наблюдаемый объект для обновления базы данных.

Код, который у меня есть, частично работает, но есть состояние гонки, при котором блокировка не всегда снимается, вероятно, потому, что подписка на this.updateIsBeingEdited$(false) не всегда завершается к моменту вызова следующего оператора return. Итак, я знаю, что это неправильно реализовано.

Как я могу сделать так, чтобы наблюдаемый this.updateIsBeingEdited$ завершился до того, как canDeactivate вернет значение?

Возвращаемое значение всегда должно быть истинным, потому что компонент всегда должен деактивироваться, ему просто нужно убедиться, что this.updateIsBeingEdited$.subscribe() выполнено до завершения деактивации.

КОМПОНЕНТ

  canDeactivate(): Observable<boolean> | boolean {

    // Check if Is Being Edited must be removed
    if (this.mustReleaseIsBeingEdited()) {
      this.removeIsBeingEditedSub = this.updateIsBeingEdited$(false).subscribe(result => {
        // QUESTION: How to wait until this is complete before allowing component to deactivate?
        return true;
      }, err => { console.error(err); }, () => { });

      // Always allow deactivation
      return true;
    } else {
      return true;
    }

  }

  private updateIsBeingEdited$(isBeingEdited): Observable<boolean> {

    const editedObj = {
      _id: this.record._id,
      IsBeingEdited: isBeingEdited,
      EditedBy: this.accessLevelService.getUserId()
    }

    return this.httpService!.postData$(
      `records/_id/${editedObj._id}/IsBeingEdited/`,
      editedObj
    );

  }

ОХРАННИК

export interface ComponentCanDeactivate {
  canDeactivate: () => boolean | Observable<boolean>;
}
/**
 * Guard to notify client that user has navigated away from route
 * Implemented in component for managing record locks only
 */
@Injectable({
  providedIn: 'root'
})
export class RecordLocksGuard implements CanDeactivate<ComponentCanDeactivate> {
  canDeactivate(component: ComponentCanDeactivate): boolean | Observable<boolean> {
    if (!component) {
      return true;
    }
    component.canDeactivate();
    // Always allow component to deactivate
    return true;
  }
}

person pengz    schedule 16.11.2019    source источник
comment
Ваш охранник не должен возвращать логическое значение. Он должен возвращать Observable ‹boolean›. И ваш метод canDeactivate () также не должен возвращать логическое значение, и он не должен подписываться на какие-либо Observable. Вместо этого он должен вернуть Observable ‹boolean› (который будет возвращен охранником).   -  person JB Nizet    schedule 17.11.2019


Ответы (1)


Спасибо, вот обновленный код, который, похоже, работает.

КОМПОНЕНТ

  canDeactivate(): Observable<boolean> | boolean {

    // Check if Is Being Edited must be removed
    if (this.mustReleaseIsBeingEdited()) {
      return this.updateIsBeingEdited$(false);
    } else {
      return of(true);
    }

  }

  private updateIsBeingEdited$(isBeingEdited): Observable<boolean> {

    const editedObj = {
      _id: this.record._id,
      IsBeingEdited: isBeingEdited,
      EditedBy: this.accessLevelService.getUserId()
    }

    return this.httpService!.postData$(
      `records/_id/${editedObj._id}/IsBeingEdited/`,
      editedObj
    );

  }

ОХРАННИК

export interface ComponentCanDeactivate {
  canDeactivate: () => boolean | Observable<boolean>;
}
/**
 * Guard to notify client that user has navigated away from route
 * Implemented in component for managing record locks only
 */
@Injectable({
  providedIn: 'root'
})
export class RecordLocksGuard implements CanDeactivate<ComponentCanDeactivate> {
  canDeactivate(component: ComponentCanDeactivate): boolean | Observable<boolean> {
    if (!component) {
      return of(true);
    }
    return component.canDeactivate();
  }
}
person pengz    schedule 17.11.2019