Объединить два объекта, но не запускать второй, пока не завершится первый. - PullRequest
0 голосов
/ 27 февраля 2020

У меня есть два модальных диалога: выбор и подтверждение. Вот рабочий код:

this.newClientId.pipe(take(1)).subscribe(
    response => this.confirmDialogService.ask('DSf').pipe(take(1)).subscribe(
        answer => answer ? this.createOrder(response) : this.goBack.next()
    )
);

Диалог выбора помещает значение в newClientId, после чего открывается диалоговое окно подтверждения, и когда пользователь подтверждает создание, тогда создается новый заказ.

Is это можно сделать без вложенности?

Все предложения, которые я нашел здесь, вызывают диалоговое окно подтверждения перед установкой newClientID.

Ответы [ 3 ]

1 голос
/ 27 февраля 2020

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

Попробуйте:

this.newClientId.pipe(
 take(1),
 switchMap(response => {
   return [of(response), this.confirmDialogService.ask('DSf')];
 }
 take(1),
).subscribe(([response, answer])=> answer ? this.createOrder(response) : this.goBack.next());
0 голосов
/ 27 февраля 2020

Существует один простой способ объединить два Observable в оператор rx.zip, чтобы избежать вложенных подписок


const client$ : Observable<object> = this.newClientId.pipe(take(1))
const dialog$ : Observable<object> = this.confirmDialogService.ask('DSf').pipe(take(1)) //  Why take(1) ? 

zip(client$, dialog$).subscribe( ([response, answer])) => {
  answer ? this.createOrder(response) : this.goBack.next();
}

И не могли бы вы пояснить, почему вы используете "pipe (take (1))" в оба случая? Может быть, это изменит мой ответ.

Является ли clientId наблюдаемым или объектом поведения?

0 голосов
/ 27 февраля 2020

Слияние внутренних и внешних наблюдаемых значений:

Для объединения внутренних и внешних наблюдаемых значений можно использовать оператор switchMap rx js.

this.newClientId
  .pipe(
    take(1),
    switchMap(
      clientId => this.confirmDialogService.ask('DSf'),
      (clientId, answer) => [clientId, answer]
    )
  )
  .subscribe(([clientId, answer]) => {
    console.log(`Received client id is: ${clientId} and confirmation from user is: ${answer}`);
    // Perform your logic now
  });

Существует несколько переопределенных версий для оператора switchMap, и я показал одну с селекторной функцией (подробнее рассмотрим второй аргумент оператора). Обычно, если функция селектора опущена, возвращается только значение внутренней наблюдаемой. Вы можете использовать функцию селектора, чтобы настроить свои выходные данные для включения значений как внешних, так и внутренних наблюдаемых, объединяя их в массив, как показано в примере выше.

Проверьте demo rx js app Я создал для вашего сценария использования в stackblitz.

Для получения дополнительной информации о switchMap и функциях селектора в switchMap, обратитесь к этой статье . Я настоятельно рекомендую go в этой статье, если вы впервые используете оператор switchMap.

АЛЬТЕРНАТИВНЫЙ МЕТОД:

Из своего фрагмента кода Я так понимаю, что вас интересует только первое значение наблюдаемого. В этом случае вместо объединения наблюдаемых можно использовать Promises и синтаксис ES6 async-await, чтобы создать элегантное и простое решение.

С Promises и asyn c -wait вы можете изменить свой фрагмент кода как показано ниже:

async getResult() {
  let clientId = await this.newClientId.toPromise();
  let answer = await this.confirmDialogService.ask('DSf'),toPromise();
  // perform your logic
}

В приведенном выше фрагменте кода метод confirmDialogService.ask() не будет вызываться, пока newClientId не вернет результат. Таким образом, вызовы asyn c происходят синхронно, и только после завершения 2 вызовов asyn c (в указанном порядке) он выполнит оставшуюся часть кода в методе.

EDIT: Обновлен ответ для решения проблемы с использованием оператора rx js.

...