Более краткий способ условно связать несколько наблюдаемых - PullRequest
2 голосов
/ 15 июня 2019

У меня есть метод для обновления «Запрос» в базе данных MySQL. Этот запрос может дополнительно содержать вложения, и в этом случае мне нужно выполнить дополнительные HTTP-запросы для обновления или добавления записей вложения (в другую таблицу БД) и загрузки файлов.

У меня есть функциональный метод для обновления запросов и необязательного пропуска HTTP-запросов на вложения, но я хотел бы узнать более краткий способ добиться этого. В общем, я новичок в Angular и RXJS, поэтому подход и использование операторов rxjs, скорее всего, не оптимальны.

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

Я искал потенциальные решения с iif, возвращая Observable.empty () и различные операторы rxjs, но, похоже, это опции в функциях карты, когда я просто хочу полностью их пропустить.

onUpdateRequest() {
    // if there are no attachments added to the request
    if (this.attachments.length <= 0) {
        this.callUpdateRequest().subscribe(() => {
            // some page and form tidy up
        });

    // there are attachments, so process the new request and then file uploads
    } else {
        this.callUpdateRequest().pipe(
            switchMap(() => {
                return of(this.attachments);
            }),
            mergeMap(attachments => {
                return attachments.map(attachment => {
                    return attachment;
                });
            }),
            mergeMap(attachment => {
              return this.attachmentsService.addAttachmentFile(attachment)
                  .pipe(map(fileData => {
                          return fileData;
                   }));
            }),
            mergeMap(fileData => {
                return this.attachmentsService.addAttachment(
                    this.requestId, fileData.fileUrl
                ).pipe(
                    map(attachments => {
                        return attachments;
                    })
                );
            }),
            takeLast(1)
        )
        .subscribe(() => {
            // some page and form tidy up
        });
    )
}

private callUpdateRequest() {
    return this.requestsService.updateRequest(
        // all the request params
    )
}

1 Ответ

1 голос
/ 15 июня 2019

В RxJs есть полезный оператор (также статический метод) iif () , который, как следует из названия, работает аналогично JS if / else.

Используется в пути

iif(
  () => state to check,
  o1,  // Observable to execute when statement is truthy
  o2   // Observable to execute when statement is falsy
)

Также есть defer(), который вам потребуется для создания наблюдаемой по требованию (в противном случае JS сначала попытается скомпилировать наблюдаемое, и это может вызвать некоторые ошибки, поэтому я использую его каждый раз, когда входящее значение используется наблюдаемой ).

Может использоваться как

iif(
  () => statmenet to check,
  defer(() => o1),
  defer(() => o2)
)

И ваш код может быть переписан следующим образом

getRequest(attachments) {
    return iif(
        () => attachments.length === 0,
        defer(() => this.callUpdateRequest()),
        defer(() => this.callUpdateRequest().pipe(
            switchMapTo(of(attachments)),
            mergeMap(attachments => {
                return attachments.map(attachment => {
                    return attachment;
                });
            }),
            mergeMap(attachment => {
              return this.attachmentsService.addAttachmentFile(attachment)
                  .pipe(map(fileData => {
                          return fileData;
                   }));
            }),
            mergeMap(fileData => {
                return this.attachmentsService.addAttachment(
                    this.requestId, fileData.fileUrl
                ).pipe(
                    map(attachments => {
                        return attachments;
                    })
                );
            }),
            takeLast(1)
        ))
    );
}

onUpdateRequest() {
   this.getRequest(this.attachments).subscribe(() => {
       // do whatever you want
   })
}

Я немного разбил ваш код, чтобы сделать его более общим и тестируемым.

P.S. Зачем писать this.attachments.length <= 0 может быть меньше 0?

...