операторы rxjs с несколькими вставками

#angular #rxjs6

#angular #rxjs6

Вопрос:

Как бы я мог использовать rxjs в Angular 6 для вставки элемента, затем после вставки мне нужно загрузить разные типы файлов в разные конечные точки с новым идентификатором элемента в качестве дочернего ключа без необходимости вкладывать все эти вызовы.

 createItemWithAttachments(data:any)
{    
   this.itemService.insert(data.item).subscribe((newItem:Item)=>{       
        //attachment type 1s 
        if(data.attachmentType1.length > 0){    
         this.attachmentService.upload(data.attachmentType1, 
            "type1", newItem.id).subscribe(newAttachment=>{

         });    
    }    

    //attachment type 2s 
    if(data.attachmentType2.length > 0){    
         this.attachmentService.upload(data.attachmentType2, 
             "type2", newItem.id).subscribe(newAttachment=>{    

         });    
    }    
    });    
}
  

Ответ №1:

Лучшим способом было бы использовать mergeMap вместе с merge и last , чтобы получить последнее переданное значение из слияния. Вы должны определить, что поместить внутрь of() . Это должно быть либо undefined / void 0 / null , если вы возвращаете объект из upload вызова, либо пустой массив [] , если вы возвращаете массив из загрузки:

 createItemWithAttachments({ item, attachmentType1: type1, attachmentType2: type2 }): void {
  this.itemService.insert(item).pipe(
    mergeMap(({ id }: Item) => {
      const mergeUpload = [
        ...(type1.length ? [this.attachmentService.upload(type1, "type1", id)] : []),
        ...(type2.length ? [this.attachmentService.upload(type2, "type2", id)] : [])
      ];

      return mergeUpload.length ? merge(...mergeUpload) : of([]);
    }),
    last()
  ).subscribe((newAttachments) => {

  });
}
  

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

1. На самом деле я возвращаю элемент из загрузки, поскольку он отображает множество других свойств, есть ли способ выполнить последний завершенный вызов?

2. новые вложения будут содержать массив с ответами массива слияния в таком порядке. Разве этого недостаточно?

3. У меня есть служба вложений, возвращающая элемент с вложенными вложениями, поэтому было интересно, как получить последний элемент, который был завершен в mergemap

4. большое вам спасибо, теперь я это улавливаю, rxjs — это сложная задача.

5. @Fab добро пожаловать, и ты прав. Количество операторов огромно! Удачи 🙂

Ответ №2:

Я думаю, что есть несколько способов сделать это, но один из способов может быть чем-то вроде:

 this.itemService.insert(data.item)
    .pipe(
        take(1),
        mergeMap((newItem:Item) => {
            const attachmentUpdateObservables = [];
            if(data.attachmentType1.length > 0){
              attachmentUpdateObservables.push(this.attachmentService.upload(data.attachmentType1, "type1", newItem.id));
            }

            if(data.attachmentType2.length > 0){
              attachmentUpdateObservables.push(this.attachmentService.upload(data.attachmentType2, "type2", newItem.id));
            }

            return combineLatest(attachmentUpdateObservables);

        })
    .subscribe(newAttachments => {
        // Do something
    });
  

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

1. У меня есть красная строка под mergeMap, она требует ObservableInput, я пытаюсь понять mergeMap, поэтому пока не уверен, чего мне не хватает. Тип ‘OperatorFunction<{}, [{}, any]>’ не может быть присвоен типу ‘ObservableInput<{}>’. Я думаю, что виновником является combineLatest, mergeMap хочет вернуть Observable

2. если предположить, что мне нужно обернуть combineLastest следующим образом: return of(combineLatest(attachmentUpdateObservables));

3. combineLatest должен возвращать наблюдаемое, поэтому не должно быть необходимости оборачивать его в of(). Я предполагаю, что ошибка может быть связана с тем, что «attachmentUpdateObservables» может быть пустым массивом. Не уверен, как combineLatest обрабатывает пустой массив, но, похоже, у PierreDuc было решение для этого с помощью «return merge. длина? forkJoin (слияние): of([]); «. Другой потенциальной причиной может быть то, что combineLatest импортирован не из того места. Должно быть «импортировать { combineLatest } из ‘rxjs’.

4. Я только что понял, что импортировал его из import { combineLatest } из ‘rxjs/ operators’; который возвращает OperaterFunction, я изменил его на import { combineLatest } из ‘rxjs’; и он действительно возвращает наблюдаемое. Большое спасибо.