Angular8 RXJS CanDeactivate在停用之前等待可观察的结果

时间:2019-11-16 23:13:34

标签: angular rxjs rxjs-observables rxjs-subscriptions candeactivate

我正在尝试使用CanDeactivate防护来检测用户何时离开该组件。目的是#1检查当前用户是否对记录拥有“正在编辑”锁,而#2如果是,则调用一个可观察对象以更新数据库。

我拥有的代码部分起作用,但是在竞争条件下,锁并不总是释放的,这可能是因为this.updateIsBeingEdited$(false)的预订在调用下一个return语句时并不总是完成的。所以我知道这没有正确实现。

在canDeactivate返回值之前,如何使this.updateIsBeingEdited$可观察对象完成?

返回值应始终为true,因为该组件应始终停用,因此只需确保在停用完成前完成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
    );

  }

GUARD

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;
  }
}

1 个答案:

答案 0 :(得分:0)

谢谢,这是似乎正在运行的更新代码。

组件

@BindingAdapter("listData")
fun bindRecyclerView(recyclerView: RecyclerView, data: List<Movie>?) {
    val adapter = recyclerView.adapter as MainAdapter
    adapter.submitList(data)
}

@BindingAdapter("posterImageUrl")
fun bindPosterImage(imgView: ImageView, imgUrl: String?) {
    imgUrl?.let {
        val imgUri = (IMAGE_BASE_URL + POSTER_SIZE + imgUrl).toUri().buildUpon().build()
        Glide.with(imgView.context)
            .load(imgUri)
            .apply(RequestOptions().placeholder(R.drawable.loading_animation).error(R.drawable.ic_broken_image))
            .into(imgView)
    }
}

GUARD

  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
    );

  }