RxJs Angular 7 HttpClient несколько POST с forkJoin удалить вторую подписку? - PullRequest
3 голосов
/ 03 мая 2019

Я создаю объект Work Item со связанными дочерними объектами Task. Моя функция (createWorkItemAndChildren) принимает два параметра: workItem и массив объектов Task. Я хочу, чтобы моя функция возвращала массив всех идентификаторов, которые были созданы (рабочий элемент и задачи).

Мне нужно вернуть родительский идентификатор из одного вызова http POST (workItemService.createWorkItem), прежде чем я смогу затем создать дочерние задачи, которые используют другой метод http POST в той же службе.

Теперь у меня есть forkJoin в createChildWorkItems, возвращающий все дочерние идентификаторы одновременно.

Как мне изменить его так, чтобы была только одна подписка, и чтобы возвращать массив с родительским и дочерним идентификаторами вместе?

  createChildWorkItems(parentId, tasks: Task[]): Observable<any> {
    return <Observable<number>> forkJoin(
      tasks.map(task => <Observable<number>> this.workItemService.createChildWorkItem(parentId, task))
    ).pipe(zip());

  }

  createWorkItemAndChildren(workItem, childTasksToSave: Task[]){
    var resultArray = [];
    this.workItemService.createWorkItem(workItem).subscribe(workItemId => {
      var parentId = workItemId;
      resultArray.push(parentId);
      if (parentId !== null){
        this.createChildWorkItems(parentId, childTasksToSave).subscribe((results: number) => {
          resultArray.push(results);
          this.tfsIdsCreated = resultArray;
        });
      }
    });
  }

Ответы [ 4 ]

2 голосов
/ 03 мая 2019

В вашей ситуации ребенок не является хорошим кандидатом для форк-соединения. но здесь вы должны использовать Async / await. fork join отправляет запрос в асинхронном режиме, но Async / await будет ожидать ответ на каждый запрос, когда вы получите ответ, прикрепите этот ответ к простому родительскому элементу, в асинхронном / ожидающем запросе будет находиться в состоянии ожидания, как цикл. когда все запросы выполнены, вернуть этот объект вот ссылка asyn / await https://lavrton.com/javascript-loops-how-to-handle-async-await-6252dd3c795/

  createWorkItemAndChildTasks(workitem, childTasksToSave: Task[]): any {
    this.workItemService.createWorkItem(workitem).subscribe(workItemId => {
     var parentId = workItemId;
      if (parentId !== null ){
        this.tfsIdsCreated.push(parentId);

    // now create the children on the workItemForm.
    for (let child of childTasksToSave){
//use here Async await when you get response attach to parent 

     this.workItemService.createChildWorkItem(parentId, child).subscribe(task =>{
        if (task !== null){
          console.log(' createWorkItem received child taskid: ' + task);
          this.tfsIdsCreated.push(task);
        }
      });
    }
  }
  return this.tfsIdsCreated;
});

}

1 голос
/ 08 мая 2019

Вот что я в итоге сделал, поэтому я принял ответ от kos: Мой массив tfsIdsCreated подписывается на результат, который предоставляет список идентификаторов.

createParentAndKids(workItem, childTasksToSave){
    this.workItemService.createWorkItem(workItem).pipe(
      mergeMap(parentId => {
        if (parentId === null){
          return of([parentId]);
        }

        const childTaskObservables$ = childTasksToSave.map(
          child => this.workItemService.createChildWorkItem(parentId, child)
        );

        return forkJoin(childTaskObservables$).pipe(
          map(ids => [parentId, ...ids])
        );

      })
    ).subscribe(x => this.tfsIdsCreated.push(x));
  }
1 голос
/ 04 мая 2019

Создайте массив наблюдаемых и передайте ссылку в forkjoin

let observableBatch= [];

for (let child of childTasksToSave){
   observableBatch.push(this.workItemService.createChildWorkItem(parentId, child));
}

Observable.forkJoin(observableBatch).subscribe...;

ссылка: https://stackoverflow.com/a/35676917/6651984

1 голос
/ 04 мая 2019

Если вы хотите выполнять подзадачи параллельно - forkJoin .

Вот пример:

createParent().pipe(
  // switch from parent stream to forkJoin(...children)
  mergeMap(parent =>
    // wait for all children to be created
    forkJoin(children.map(child => createChild(parent, child))).pipe(
      // combine childResults with parent
      map(childResults => {
        // do operations with parent and all children
        parent.childResults = childResults;
        // switch back to parent
        return parent;
      })
    )
  )
)
.subscribe(parent => {
  // ...
})

Обратите внимание, что мы подписываемся на Observable только один раз - это хорошая практика.

Вам не нужно async await здесь.

Надеюсь, это поможет

...