Home > Software design >  How dont create stream each time after change input?
How dont create stream each time after change input?

Time:10-22

I have the following code:

public upload(): void {
    const fileinput = document.getElementById('file');
    fileinput.click();
    fileinput.addEventListener('change', this.handleFileInput.bind(this));
}

private handleFileInput(event) {
    try {
        const input = event.target as HTMLInputElement;
        const reader = new FileReader();
        const { objectId } = this.object;
        const file = input.files[0];

        reader.onload = () => {
            event.target.value = null;
            this.objectDetailsService
                .upload(file, objectId)
                .subscribe(
                    () => //,
                    () => //,
                );
        };
        reader.readAsArrayBuffer(file);
    } catch (e) {
        console.log(e);
    }
}

I should allow to load the same file sometimes. When user select another this code create as new stream. How to avoid it?

CodePudding user response:

You're right in asking how to apply switchMap. One way is to create an observable to handle the async callback onload. Then you could apply operators like switchMap to call other async functions.

Also I'd suggest attaching the event handler directly in the template instead of using document.getElementById('file'); in the controller.

Try the following

*.ts

import { Observable, Observer, timer } from 'rxjs';
import { switchMap } from 'rxjs/operators';

public handleFileInput(event) {
  const input = event.target as HTMLInputElement;
  const file = input.files[0];
  this.readFile(file).pipe(
    switchMap((file: any) => {
      const { objectId } = this.object;
      return this.objectDetailsService.upload(file, objectId);
    })
  ).subscribe({
    next: () => console.log('File uploaded'),
    error: (error: any) => console.log('Error:', error),
  });
}

readFile(file): Observable<any> {
  const reader = new FileReader();
  reader.readAsArrayBuffer(file);

  return new Observable((observer: Observer<any>) => {
    reader.onload = (ev: ProgressEvent) => {
      observer.next(file);
      observer.complete();
    };
    reader.onerror = (error: any) => {
      observer.error(error);
    };
  });
}

*.html

Select file: <input type="file" (change)="handleFileInput($event)" />

Working example: Stackblitz

  • Related