Ошибка Angular Rxjs forkJoin: невозможно прочитать свойство «подписаться» на неопределенное

Я пытаюсь добавить несколько вложений в элемент списка SharePoint. Метод службы принимает список вложений и должен возвращать ответ только после загрузки всех файлов (Sharepoint API принимает только один файл за раз). Поэтому для этой цели я использую rxjs forkJoin.

Ниже приведен класс обслуживания, который я написал.

import { Injectable } from '@angular/core';
import { Observable, forkJoin } from 'rxjs';
import { HttpClient, HttpHeaders } from '@angular/common/http'
import { ContextService } from './context.service'
import { mergeMap } from 'rxjs/operators';

@Injectable({
  providedIn: 'root'
})
export class AttachmentService {

  constructor(private httpClient: HttpClient) { }

  addAttachmentsToTheList(listName: string, listItemId: number, attachmentList: any[], diagest: any) {
    //get the file upload observable list
    let fileUploadOnservables: any[] = [];
    attachmentList.forEach(file => {
      fileUploadOnservables.push(this.addAttachment(listName, listItemId, file, diagest))
    });

    // use forkJoin to combine the operations and subscribe to all results
      // use forkJoin to combine the operations and subscribe to all results
      forkJoin(fileUploadOnservables)
      .subscribe(
        (response) => {
        //after all the successful requests do something
      }
      );
  }

}

  //this will add a single attachment to list
  addAttachment(listName: string, listItemId: number, file: any, diagest: any) {
    //first read the file as buffer, and pass the buffer to the Sharepoint REST API
    return this.getFileBuffer(file)
      .pipe(
        mergeMap((fileBuffer: any) => {
          //once file buffer observable returns pass the buffer to the Sharepoint REST API
          return this.httpClient.post(
            "../_api/lists/GetByTitle('" + listName + "')/items(" + listItemId + ")/AttachmentFiles/add(FileName='" + file.name + "')",
            fileBuffer,
            {
              headers: new HttpHeaders({
                'X-RequestDigest': diagest,
                'Accept': 'application/json; odata=verbose',
                'Content-Type': 'application/json; odata=verbose'
              })
            })
        })
      );
  }

  //this returns the file buffer
  getFileBuffer(file) {
    return new Observable(subscriber => {
      var reader = new FileReader();
      reader.readAsArrayBuffer(file);
      reader.onload = function (e: any) {
        subscriber.next(e.target.result);
        subscriber.complete();
      };
    });
  }
}

В компоненте:

someMethod(){
 this.attachmentService.addAttachmentsToTheList('SomeList', 1, this.attachmentList,diagest)
   .subscribe(
   (result: any) => {
       //do something
    },
    (error: any) => {
       //handle error
    });

}

Этот код выдает ошибку ниже, но также загружает файл. Что я делаю не так, как исправить эту ошибку?

Cannot read property 'subscribe' of undefined

Ценю вашу помощь.


person Nilmi Nawalage    schedule 12.12.2020    source источник
comment
Ради интереса: показывает ли трассировка стека, что ошибка возникает в методе addAttachmentsToTheList или в компоненте, вызывающем службу?   -  person tnc1997    schedule 12.12.2020
comment
я предполагаю, что attachmentList пуст или не определен.   -  person Aakash Garg    schedule 12.12.2020
comment
Список вложений @AakashGarg не пуст, код фактически проверяет наличие пустого и возвращает результат в верхней части метода, хотя я не указал его здесь.   -  person Nilmi Nawalage    schedule 12.12.2020
comment
можете ли вы указать трассировку стека ошибок и распечатать fileUploadOnservables после цикла.   -  person Aakash Garg    schedule 12.12.2020
comment
@ tnc1997 трассировка стека указывает на ошибку компонента, вызывающего службу. Но то, что я сделал, в основном подписано на addAttachmentsToTheList. Обновлен код, чтобы показать, что на самом деле делает forkSubscribe.   -  person Nilmi Nawalage    schedule 12.12.2020


Ответы (1)


Оригинальный ответ

Похоже, ошибка вызвана тем, что вы подписываетесь на результат метода в службе из компонента, однако метод в службе фактически ничего не возвращает компоненту. Вы сможете устранить эту ошибку, вернув результат forkJoin из метода в службе и переместив subscribe() из метода в службе в компонент. Я бы порекомендовал добавить возвращаемые типы к вашим методам, так как это должно помочь лучше отлавливать ошибки, подобные этой, в будущем.

  addAttachmentsToTheList(listName: string, listItemId: number, attachmentList: any[], diagest: any): Observable<...> {
    //get the file upload observable list
    let fileUploadOnservables: any[] = [];
    attachmentList.forEach(file => {
      fileUploadOnservables.push(this.addAttachment(listName, listItemId, file, diagest))
    });

    // use forkJoin to combine the operations and subscribe to all results
    return forkJoin(fileUploadOnservables);
  }

Если вам нужно выполнить дальнейшие операции в службе после того, как вы подключились к fileUploadOnservables, вы можете использовать pipe:

return forkJoin(fileUploadOnservables).pipe(...);

Обновленный ответ

Вы можете попробовать использовать оператор from, чтобы разделить список значений на отдельные события, а затем оператор toArray для объединения каждого из событий. .

  addAttachmentsToTheList(listName: string, listItemId: number, attachmentList: any[], diagest: any): Observable<...> {
    return from(attachmentList).pipe(mergeMap(value => this.addAttachment(listName, listItemId, value, diagest)), toArray());
  }
person tnc1997    schedule 12.12.2020
comment
Я обновил код таким образом, и все равно выдает ту же ошибку. Подписчик метода компонента никогда не попадает. - person Nilmi Nawalage; 12.12.2020
comment
Не могли бы вы поделиться обновленным кодом сервиса и кодом компонента? - person tnc1997; 12.12.2020
comment
Я разместил обновленный код - person Nilmi Nawalage; 12.12.2020
comment
Я только что опубликовал обновление к своему ответу, не могли бы вы попробовать и сообщить мне? - person tnc1997; 12.12.2020