Search code examples
angulartypescriptobservableng2-file-upload

Creating an Observable that binds to an existing function


I've been trying to bind the onCompleteItem array function from the ng2-file-upload package to an RxJS Observable method that I can subscribe to.

Here is function I'm talking about:

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

..which in use is almost the same as:

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

Here's the relevant parts from MyComponent, which is currently working:

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

}

My attempt at binding this into an Observable was through the use of the RxJS bindCallback function:

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

This does not work, because of a few type/syntax errors. Does anyone have any good suggestions on how to get this rewritten as a bound Observable function?


Solution

  • bindCallback wraps a function that's called whenever the observable is subscribed to, e.g. getJSON(url, callback). You're trying to use it just by passing the callback parameter.

    Instead you can try the fromEventPattern function, which allows you to specify via its two parameters how you register the event handler, and also unregister.

    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>