Angular2 - Load binary image data asynchronously i

2020-07-24 04:59发布

问题:

I'm trying to load some images using node's fs module. I have it working on a single image but what is the correct way to do this inside an ngFor loop?

Currently I have:

<div *ngFor="let job of getJobs() | async">
   <img src={{readImageFile(job.thumbUrl)}}>
</div>

getJobs() returns an observable from my service.

readImageFile() calls a Meteor server-side method which loads the image data using fs and returns it asynchronously:

  readImageFile(url) {
    if (url) {
      this.call('readImageFile', url, function(err, res) {
        if (err) {
          console.log(err);
        }
        else {
          console.log('read image file success');
          return "data:image/jpg;base64," + res;
        }
      });
    }
  }

This doesn't work.. So what is the correct method for asynchronously loading data inside an ngFor loop?

update

I tried with readImageFile(url) | async

readImageFile: function(url) { 
  var Future = Npm.require('fibers/future'); 
  var myFuture = new Future(); 
  fs.readFile(String(url), 
  function read(error, result) { 
    if(error){ 
      myFuture.throw(error); 
    } else { 
      myFuture.return(new Buffer(result).toString('base64')); 
    } 
  }); 
  return myFuture.wait(); 
}

回答1:

This is not a good approach. readImageFile(job.thumbUrl) will be called with each change detection run which is quite often.

This should work

<img [src]="readImageFile(job.thumbUrl) | async">

The | async pipe should prevent change detection calling readImageFile() repeatedly.

Another approach would be to fill an array and bind to this array instead

getJobs() {
  this.jobs = /*code to get jobs*/.map(jobs => {
    this.images = new Array(jobs.length);
    jobs.forEach(item, idx => { 
      readImageFile(idx, item.thumbUrl);
    });
    return jobs;
  });
}
  readImageFile(idx, url) {
    if (url) {
      this.call('readImageFile', url, (err, res) => {
        if (err) {
          console.log(err);
        }
        else {
          console.log('read image file success');
          this.images[idx] = "data:image/jpg;base64," + res;
        }
      });
    }
  }
<div *ngFor="let job of jobs | async; let idx=index">
   <img [src]="images[idx]">
</div>