我正在编写一个Angular应用程序,它使用ReactiveX API来处理异步操作。我之前在Android项目中使用过API,我非常喜欢它如何简化并发任务处理。但有一件事我不确定如何以正确的方式解决。
如何从正在进行的任务中更新观察者?在这种情况下的任务将花费时间来加载/创建复杂/大型对象,并且我能够返回中间进度,但不能返回对象本身。 observable只能返回一个dataType。因此,我知道两种可能性。
创建一个具有进度字段和数据字段的对象。可以使用Observable.onNext(object)返回此对象。进度字段将在每个onNext上更新,而数据字段为空,直到最后一个onNext,这将把它设置为加载的值。
创建两个可观察对象,一个数据可观察对象和一个进度可观察对象。观察者可以订阅进度更新可观察的进度以及最终加载/创建数据时可通知的数据。这些也可以选择性地压缩在一起订阅。
我使用了这两种技术,它们都有效,但我想知道是否有统一的标准,干净的方式,如何解决这个任务。当然,它也可以是一个全新的。我为每个解决方案开放。
答案 0 :(得分:2)
仔细考虑之后我用了一个 在我的问题中类似于选项二的解决方案。 主要的观察结果与实际结果有关 操作。 在这种情况下是一个http请求,但File迭代示例类似。 它由“工作”功能返回。
可以通过函数参数添加第二个Observer / Subscriber。该订户仅关注 进度信息。这样所有操作都是nullsafe,不需要进行类型检查。
工作函数的第二个版本,没有进度Observer, 如果不需要进行UI更新,则可以使用它。
export class FileUploadService {
doWork(formData: FormData, url: string): Subject<Response> {
return this.privateDoWork(formData, url, null);
}
doWorkWithProgress(formData: FormData, url: string, progressObserver: Observer<number>): Subject<Response> {
return this.privateDoWork(formData, url, progressObserver);
}
private privateDoWork(formData: FormData, url: string, progressObserver: Observer<number> | null): Subject<Response> {
return Observable.create(resultObserver => {
let xhr: XMLHttpRequest = new XMLHttpRequest();
xhr.open("POST", url);
xhr.onload = (evt) => {
if (progressObserver) {
progressObserver.next(1);
progressObserver.complete();
}
resultObserver.next((<any>evt.target).response);
resultObserver.complete()
};
xhr.upload.onprogress = (evt) => {
if (progressObserver) {
progressObserver.next(evt.loaded / evt.total);
}
};
xhr.onabort = (evt) => resultObserver.error("Upload aborted by user");
xhr.onerror = (evt) => resultObserver.error("Error");
xhr.send(formData);
});
}
这是函数的调用,包括进度订阅者。使用此解决方案,上传功能的调用者必须 创建/处理/拆除进度订阅者。
this.fileUploadService.doWorkWithProgress(this.chosenSerie.formData, url, new Subscriber((progress) => console.log(progress * 100)).subscribe(
(result) => console.log(result),
(error) => console.log(error),
() => console.log("request Completed")
);
总的来说,我将此解决方案推荐给具有单个订阅的“配对”对象。没有空处理nececcary,和 我对问题进行了彻底的分离。
该示例使用Typescript编写,但其他ReactiveX实现应该可以使用类似的解决方案。