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());
}
我正在尝试向 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());
}