Angular Rxjs forkJoin error: Cannot read property 'subscribe' of undefined

Angular Rxjs forkJoin error: Cannot read property 'subscribe' of undefined

我正在尝试向 SharePoint 列表项添加多个附件。服务方法接受附件列表,它应该 return 只有在所有文件上传后才响应(Sharepoint API 一次只接受一个文件)。所以我为此目的使用 rxjs forkJoin。

下面是我写的服务class

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

感谢您的帮助。

原答案

看起来错误是由您从组件订阅服务中方法的结果这一事实引起的,但是服务中的方法实际上并没有 returning 任何东西组件。您应该能够通过 return 从服务中的方法获取 forkJoin 的结果并将 subscribe() 从服务中的方法移动到组件来解决此错误。我建议将 return 类型添加到您的方法中,因为这应该有助于将来更好地捕获与此类似的错误。

  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);
  }

如果你在fork加入fileUploadOnservables后需要在服务中进行进一步的操作,那么你可以使用pipe函数:

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

更新答案

您可以尝试使用 from operator to split the list of values into individual events and then the toArray 运算符来组合每个事件。

  addAttachmentsToTheList(listName: string, listItemId: number, attachmentList: any[], diagest: any): Observable<...> {
    return from(attachmentList).pipe(mergeMap(value => this.addAttachment(listName, listItemId, value, diagest)), toArray());
  }