【问题标题】:Creating an Observable that binds to an existing function创建绑定到现有函数的 Observable
【发布时间】:2020-06-08 14:21:53
【问题描述】:

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

这是我正在谈论的功能:

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

..which 在使用中几乎相同为:

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 中是通过使用 RxJS bindCallback 函数:

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 函数有任何好的建议吗?

【问题讨论】:

    标签: angular typescript observable ng2-file-upload


    【解决方案1】:

    bindCallback 包装了一个函数,该函数在订阅 observable 时调用,例如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>

    【讨论】:

      【解决方案2】:

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

      以下是我最初采用的一些可行的解决方案,最后列出的解决方案是我最终实施的解决方案。

      初步解决方案:

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

      【讨论】:

        猜你喜欢
        • 1970-01-01
        • 2015-09-21
        • 1970-01-01
        • 1970-01-01
        • 2017-05-16
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        相关资源
        最近更新 更多