创建绑定到现有函数的Observable



我一直在尝试将ng2-file-upload包中的onCompleteItem数组函数绑定到我可以订阅的RxJS Observable方法。

这是我所说的功能:

onCompleteItem(item: FileItem, response: string, status: number, headers: ParsedResponseHeaders): any;

在使用中几乎与相同

onCompleteItem(item: any, response: any, status: any, headers: any)

以下是MyComponent中的相关部分,该部分目前正在工作:

imageArray: Image[] = [];
uploader:FileUploader = new FileUploader({
url: '/api/FileUpload'
});
ngOnInit() {
this.uploader.onCompleteItem = (item: any, response: any, status: any, headers: any) => {
const data = JSON.parse(response);
data.forEach(x => {
console.log(x);
this.imageArray.push(x);
}
this.uploader.removeFromQueue(item);
};
}

我尝试将其绑定到Observable中是通过使用RxJSbindCallback函数:

bindCallback(this.uploader.onCompleteItem, {item: any, response: any, status: any, headers: any})().pipe(
tap((item, response) => {
const data = JSON.parse(response);
this.uploader.removeFromQueue(item);
const images = data.map(x => console.log(x) );
this.imageArray.push(...images);
})
).subscribe();

由于一些类型/语法错误,此操作不起作用。有人对如何将其重写为绑定的Observable函数有什么好的建议吗?

bindCallback封装了一个函数,该函数在订阅可观察对象时被调用,例如getJSON(url, callback)。您正试图通过传递callback参数来使用它。

相反,您可以尝试fromEventPattern函数,该函数允许您通过其两个参数指定如何注册事件处理程序,以及如何注销。

const {fromEventPattern} = rxjs;
const uploader = {
upload() {
setTimeout(() => {
if (this.onCompleteItem) this.onCompleteItem('arg 1', 'arg 2');
}, 1000);
}
};
const source = fromEventPattern(handler => uploader.onCompleteItem = handler, _ => uploader.onCompleteItem = null);
source.subscribe(([arg1, arg2]) => console.log(arg1, arg2));
uploader.upload();
<script src="https://cdnjs.cloudflare.com/ajax/libs/rxjs/6.5.4/rxjs.umd.js"></script>

这是一次真正的旅程。。但我希望这个答案能给一些用户带来新的见解。

以下是我最初采用的几个有效的解决方案,最后列出的解决方案是我最终实现的解决方案。

初始解决方案:

const obs = new Observable<{ item: FileItem, response: string }>(sub => {
this.uploader.onCompleteItem = (item: FileItem, response: string) => sub.next({ item, response });
return () => this.uploader.onCompleteItem = undefined;
});
bindCallback((x: (item: FileItem, response: string) => any) => this.uploader.onCompleteItem = x)()
.pipe(
takeUntil(this.onDestroySubj),
tap(([item, response]) => {
const data = JSON.parse(response);
this.imageArray.push(...data );
this.uploader.removeFromQueue(item);
})
).subscribe();

上述解决方案的唯一问题是bindCallBack只触发一次。

更精细的解决方案:

Observable.create((sub: Subscriber<[FileItem, string]>) => {
this.uploader.onCompleteItem = (item: FileItem, response: string) => sub.next([item, response]);
return () => this.uploader.onCompleteItem = undefined;
}).pipe(
takeUntil(this.onDestroySubj),
tap(([item, response]) => {
const data = JSON.parse(response);
this.imageArray.push(...data );
this.uploader.removeFromQueue(item);
})
).subscribe();

这让我思考。。我考虑使用fromEvent,因为它订阅了jQuery操作和浏览器事件,但除非编写了包装器,否则不会订阅。这就是我使用fromEventPattern:得出最终解决方案的原因

最终解决方案:(完整代码(

ngOnInit() {
fromEventPattern<Parameters<FileUploader['onCompleteItem']>>(x => this.uploader.onCompleteItem = x).pipe(
takeUntil(this.onDestroySubj),
tap(([item, response]) => {
this.imageArray = this.imagesSubject.getValue();
const data = JSON.parse(response);
this.imageArray.push(...data );
this.uploader.removeFromQueue(item);
// because I'm using a Subject
this.imagesSubject.next(this.imageArray);
})
).subscribe();
}
ngOnDestroy() {
this.onDestroySubj.next();
}

最新更新