Обеспечение выполнения первого наблюдаемого объекта перед запуском второго (сложного) объекта

#angular #rxjs

#angular #rxjs

Вопрос:

У меня возникли некоторые проблемы с упорядочением двух наблюдаемых объектов, чтобы первый выполнялся перед вторым. Я начал пытаться использовать concatMap без какой-либо удачи … возможно, это не лучший вариант, но, основываясь на описаниях операторов отображения более высокого порядка, я подумал, что это лучший.

Первый наблюдаемый объект, который необходимо запустить, очень прост:

 this.workflowService.getFolderActions().subscribe(tasks => {
  this.tasks = tasks;
});
  

Для правильной работы второго наблюдаемого объекта требуется свойство tasks (или this.tasks ). Второй наблюдаемый объект:

 this.route.data
.pipe(
  switchMap(x => {
    return this.route.paramMap;
  }))
.subscribe(params => {
  this.paymentId = params.get('id');
  this.task = this.workflowService.getTask(this.paymentId);
  this.paymentData = <PaymentData>this.task.actionData;

  const incompleteOptionalTasks = this.workflowService.getIncompleteOptionalTasks();
  const nextRequiredTask = this.getIncompleteRequired();
  this.nextTask = nextRequiredTask;

  if (!nextRequiredTask amp;amp; incompleteOptionalTasks) {
    this.nextTask = this.tasks.find(task => task.id !== this.paymentId);
  } else if (nextRequiredTask) {
    this.nextTask = nextRequiredTask;
  }
});
  

Поскольку во втором наблюдаемом объекте есть switchMap , я довольно растерян. Я начал пытаться выписать concatMap для этих двух:

 this.workflowService.getFolderActions().pipe(
  tap(tasks => this.tasks = tasks),
  concatMap(tasks => {
    this.route.data.pipe(
      switchMap(x => {
        return this.route.paramMap;
      })
    )
  })
);
  

… но я получаю сообщение об ошибке: 'tasks' is declared but its value is never read. Однако я уверен, что я неправильно подхожу к этому, поэтому любая помощь будет высоко оценена.

Ответ №1:

Рассмотрите возможность его реализации следующим образом:

 this.workflowService.getFolderActions().
  pipe(
    tap(tasks => this.tasks = tasks),
    switchMapTo(this.route.paramMap)
  )
  .subscribe(params => {
    this.paymentId = params.get('id');
    this.task = this.workflowService.getTask(this.paymentId);
    this.paymentData = <PaymentData>this.task.actionData;

    const incompleteOptionalTasks = this.workflowService.getIncompleteOptionalTasks();
    const nextRequiredTask = this.getIncompleteRequired();
    this.nextTask = nextRequiredTask;

    if (!nextRequiredTask amp;amp; incompleteOptionalTasks) {
      this.nextTask = this.tasks.find(task => task.id !== this.paymentId);
    } else if (nextRequiredTask) {
      this.nextTask = nextRequiredTask;
    }
  });
  

При необходимости вы можете захотеть получить tasks в функции подписки вместо сохранения ее глобально:

  this.workflowService.getFolderActions().
  pipe(
    tap(tasks => this.tasks = tasks),
    withLatestFrom(this.route.paramMap)
  )
  .subscribe(([tasks, params]) => {
    this.paymentId = params.get('id');
    this.task = this.workflowService.getTask(this.paymentId);
    this.paymentData = <PaymentData>this.task.actionData;

    const incompleteOptionalTasks = this.workflowService.getIncompleteOptionalTasks();
    const nextRequiredTask = this.getIncompleteRequired();
    this.nextTask = nextRequiredTask;

    if (!nextRequiredTask amp;amp; incompleteOptionalTasks) {
      this.nextTask = tasks.find(task => task.id !== this.paymentId);
    } else if (nextRequiredTask) {
      this.nextTask = nextRequiredTask;
    }
  });
  

Комментарии:

1. Вау, это так невероятно полезно — я не был так хорошо знаком с операторами withLatestFrom и switchMapTo — читаю о них сейчас. Большое вам спасибо, я действительно ценю помощь!

Ответ №2:

В вашем случае switchMap оператор выбран правильно, потому что он имеет доступ к значению из первого наблюдаемого, где вы можете оперировать этим значением, а затем вы также должны вернуть наблюдаемое.

 this.workflowService.getFolderActions()
 .pipe(
  switchMap((tasks ) => {
   this.tasks = tasks;
   return this.route.paramMap;
 })
 .subscribe(() => ...)