Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

How to load images async with RxJs and perform a method when all loaded

I am trying to convert my promise based code to RxJs but have a hard time to get my head around Rx especially RxJs.

I have a an array with paths.

var paths = ["imagePath1","imagePath2"];

And I like to load images in Javascript

var img = new Image();
img.src = imagePath;
image.onload // <- when this callback fires I'll add them to the images array

and when all Images are loaded I like to execute a method on.

I know there is

Rx.Observable.fromArray(imagepathes)

there is also something like

Rx.Observable.fromCallback(...)

and there is something like flatMapLatest(...) And Rx.Observable.interval or timebased scheduler

Based on my research I would assume that these would be the ingredients to solve it but I cannot get the composition to work.

So how do I load images from a array paths and when all images are loaded I execute a method based on an interval?

Thanks for any help.

like image 365
silverfighter Avatar asked Jul 12 '15 10:07

silverfighter


2 Answers

I think you don't have to create an Observable yourself for this.

import { from, fromEvent } from 'rxjs';
import { mergeMap, map, scan, filter } from 'rxjs/operators';

const paths = ["imagePath1","imagePath2"];

from(paths).pipe(
   mergeMap((path) => {
      const img = new Image();

      img.src = path;
      return fromEvent(img, 'load').pipe(
          map((e) => e.target)
      );
   }),
   scan((acc, curr) => [...acc, curr], []),
   filter((images) => images.length === paths.length)
).subscribe((images) => {
   // do what you want with images
});
like image 159
DongBin Kim Avatar answered Oct 19 '22 23:10

DongBin Kim


At first you need a function that will create a Observable or Promise for separate image:

function loadImage(imagePath){
   return Rx.Observable.create(function(observer){
     var img = new Image();
     img.src = imagePath;
     img.onload = function(){
       observer.onNext(img);
       observer.onCompleted();
     }
     img.onError = function(err){
       observer.onError(err);
     }
   });
}

Than you can use it to load all images

Rx.Observable
  .fromArray(imagepathes)
  .concatMap(loadImage) // or flatMap to get images in load order
  .toArray()
  .subscribe(function(images){
    // do something with loaded images
  })
like image 37
Bogdan Savluk Avatar answered Oct 20 '22 00:10

Bogdan Savluk