2

I'm writing an application draws particles on screen in a chemical reaction.

I have written a Particle class and want to handle the async nature of loading images in P5.js in this class.

My thinking was that if I wrap the loadImage() function in a Promise, I should be able to load all of my particle sprites async and then have the draw code execute as soon as the P5 Image object resolves.

I had this code working fine using just callback functionality of loadImage(), but I ultimately have to hand off the image object to a physics library to model particle motion as well as other constructors, so a Promise pattern seemed to be the right solution.

class Particle {

    constructor(name) {
        // Set properties on the Particle
        this.imageUrl = "THE_URL";
        this.imageObject = null;
    }

    loadParticleImage() {

        console.log("attempting to load image: " + this.imageUrl)

        return new Promise(function (resolve, reject) {
            loadImage(this.imageUrl, (result) => {

                // Sets the image object property to the result for other methods to access
                this.imageObject = result;

                // Resolves the Promise with the result
                resolve(result);

            }, reject(Error("Image not found")));
        })
    }

    drawParticle() {

        console.log("attempting to draw particle");

        this.loadParticleImage().then(function (imageObject) {

            // code to draw image and handoff to physics library

        }, function (error) {
            console.log("imageObject not defined", error);
        });

    }

}

And in the setup() function of the main sketch file, I would initialize a particle and draw it using something like:

theParticle = new Particle("Water");
theParticle.drawParticle();

I get a stack error saying that the image could not be loaded and I can't quite figure out why.

attempting to draw particle
particle.js: attempting to load image: img/svg/Water.svg
particle.js: imageObject not defined Error: Image not found
at particle.js
at new Promise (<anonymous>)
at Particle.loadParticleImage (particle.js)
at Particle.drawParticle (particle.js)
at <anonymous>:1:18
dfd0226
  • 321
  • 1
  • 2
  • 10
  • `drawParticle` should only draw the loaded particle, not load it. Otherwise rename the method to `loadAndDrawParticle`. – Bergi Jan 12 '19 at 19:39

1 Answers1

2

I can spot two mistakes in your code:

  • you are always immediately calling reject(). You probably wanted to pass a callback to loadImage that will reject the promise:

    loadImage(this.imageUrl, (result) => {
        …
    }, () => {
    // ^^^^^^^
       reject(new Error("Image not found"));
    });
    
  • the this keyword in your callback is not the one you expect. Use an arrow function for the promise executor callback as well to have this refer to your Particle instance that loadParticleImage was called on:

    return new Promise((resolve, reject) => {
    //                                   ^^
        loadImage(this.imageUrl, result => {
            this.imageObject = result;
            …
    
Bergi
  • 630,263
  • 148
  • 957
  • 1,375
  • Oh wow, thank you for pointing out these syntax problems. I just started to read about Promises the same day I was adapting this code, so definitely still learning. Much appreciate the insight! – dfd0226 Jan 13 '19 at 17:57