首页 > 解决方案 > 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

感谢你的帮助。

标签: angularrxjsobservablefork-joinforkjoinpool

解决方案


原始答案

看起来错误是由于您从组件订阅服务中方法的结果而引起的,但是服务中的方法实际上并未向组件返回任何内容。您应该能够通过从服务中的方法返回结果并将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);
  }

如果你在 fork 加入后需要在服务中执行进一步的操作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());
  }

推荐阅读