# How do i ensure preload() has finished?

**URL:** <https://discourse.processing.org/t/how-do-i-ensure-preload-has-finished/30006>\
**Category:** Libraries\
**Created:** [May 10, 2021, 6:57am UTC](https://discourse.processing.org/t/how-do-i-ensure-preload-has-finished/30006 "2021-05-10T06:57:54Z")\
**Posts on this page:** 8\
**Page:** 1

<div class="post-metadata">

**Author:** ![whatsinausername](https://avatars.discourse-cdn.com/v4/letter/w/e0b2c6/32.png) [@whatsinausername](https://discourse.processing.org/u/whatsinausername)\
**Post date:** [May 10, 2021, 6:57am UTC](https://discourse.processing.org/t/how-do-i-ensure-preload-has-finished/30006/1 "2021-05-10T06:57:54Z")

</div>

i’m attempting to use p5.js for some audio processing and phaser.js for some game code.

```auto
function phaser_preload() {
    boop = loadSound('boop.wav');
}
function phaser_create() {
    fft = new p5.FFT();
    boop.play();
    fft.setInput(boop);
}
function phaser_update(time, dt) {
    fft.analyze();
}
new p5();
var game, boop, fft;
game = new Phaser.Game(config)

```

but `boop.play()` in `phaser_create` throws an error if boop hasn’t finished loading. is there a way to ensure that `phaser_preload` doesn’t return before `loadSound` has completely finished?

---

<div class="post-metadata">

**Author:** ![KumuPaul](https://yyz2.discourse-cdn.com/flex036/user_avatar/discourse.processing.org/kumupaul/32/13072_2.png) [@KumuPaul](https://discourse.processing.org/u/KumuPaul)\
**Post date:** [May 10, 2021, 7:32am UTC](https://discourse.processing.org/t/how-do-i-ensure-preload-has-finished/30006/2 "2021-05-10T07:32:55Z")

</div>

Your example code appears to be incomplete and unusually structured:

- You create a `p5` instance, but you don’t pass a callback to it
- You don’t have a `setup` function
- You don’t appear to call `phaser_preload()` anywhere.

If you want to leverage the p5.js preload functionality you either need to have a global `preload` function if using global mode, or pass a callback to the `p5` constructor which defines a `preload` function. I suggest you review the docs covering sketch [“Structure”](https://p5js.org/reference/#group-Structure). (See examples below)

If you have a properly structured sketch with a `preload` function, then any p5.js resources for which you initiate loading in that preload function will be fully loaded when `setup` is called.

An alternative would be to use the callback parameters of the loadSound function: `loadSound(path, [successCallback], [errorCallback], [whileLoading])`. If specified, either `successCallback` or `errorCallback` will be called when loading is complete.

In case you do want to use the preload function, here are some valid examples.

GlobalMode:

```auto
let boop;

function preload() {
  boop = loadSound('boop.wav');
}

function setup() {
  if (boop.isLoaded()) {
    // This should be printed to the console
    print('Can has boop!');
  }
}

// No need to create an instance of p5 the sketch should initialize automatically

```

Instance Mode:

```auto
function boopSketch(p) {
  let boop;

  p.preload = function() {
    boop = loadSound('boop.wav');
  }

  p.setup = function() {
    if (boop.isLoaded()) {
      // This should be printed to the console
      print('Can has boop!');
    }
  }
}

let instance = new p5(boopSketch);

```

---

<div class="post-metadata">

**Author:** ![whatsinausername](https://avatars.discourse-cdn.com/v4/letter/w/e0b2c6/32.png) [@whatsinausername](https://discourse.processing.org/u/whatsinausername)\
**Post date:** [May 10, 2021, 7:33am UTC](https://discourse.processing.org/t/how-do-i-ensure-preload-has-finished/30006/3 "2021-05-10T07:33:41Z")

</div>

i ended up using a “”“reference”"" count:

```auto
loading = 0;
function preload() {
    loading += 1;
    boop = loadSound('boop.wav', () => loading -= 1);
}
async function begin() {
    new p5();
    while(loading > 0) {
        await new Promise(resolve => setTimeout(resolve, 100));
    }
    var game, boop;
    game = new Phaser.Game(config);
}
begin()

```

less hack-y solutions are definitely welcome though

---

<div class="post-metadata">

**Author:** ![whatsinausername](https://avatars.discourse-cdn.com/v4/letter/w/e0b2c6/32.png) [@whatsinausername](https://discourse.processing.org/u/whatsinausername)\
**Post date:** [May 10, 2021, 7:37am UTC](https://discourse.processing.org/t/how-do-i-ensure-preload-has-finished/30006/4 "2021-05-10T07:37:57Z")

</div>

i tried cutting out as much irrelevant code as i could

- had no idea i was supposed to pass it a callback, the docs for on-demand global mode didn’t mention it
- setup is being done in the phaser\_create function
- the phaser functions are called by phaser. they’re specified in a config that i didn’t include; full config below

```auto
var config = {
    type: Phaser.AUTO,
    width: 160*3,
    height: 144*3,
    backgroundColor: '#64a5ff',
    pixelArt: true,
    scene: {
        preload: phaser_preload,
        create: phaser_create,
        update: phaser_update
    },
};

```

i tried using a global preload function, but it would return before fully preloading the sound, and phaser would try to play `boop` before it was finished loading. i didn’t want to set up a whole sketch since i just need p5 for the `fft` bits

---

<div class="post-metadata">

**Author:** ![KumuPaul](https://yyz2.discourse-cdn.com/flex036/user_avatar/discourse.processing.org/kumupaul/32/13072_2.png) [@KumuPaul](https://discourse.processing.org/u/KumuPaul)\
**Post date:** [May 10, 2021, 8:21am UTC](https://discourse.processing.org/t/how-do-i-ensure-preload-has-finished/30006/5 "2021-05-10T08:21:13Z")

</div>

If you want to use global mode with preload I suggest you do something like:

```auto
let boop;
let game;

// p5.js invokes this automatically, do not invoke it yourself
function preload() {
  boop = loadSound('boop.wav');
}

// p5.js invokes this automatically, do not invoke it yourself
function setup() {
  noCanvas();
  // At this point you are guaranteed that boop is loaded.
  game = new Phaser.Game(config);
  // Any code that expects game to have been initialized should be called from here.
}

```

From my testing I found the following:

- If there is no global `setup` function and no call to the `p5` constructor, then `p5.sound` is not loaded and `preload` is never called.
- With the call to `noCanvas()` in `setup`, there isn’t any perceptible overhead to this approach (without it p5.js does create a default canvas element).
- Calling the parameterless `p5` constructor forces the initialization of `p5.js` in global mode even if there is no `setup` function, but this includes the default overhead of creating a canvas and also generates a warning `p5.js seems to have been imported multiple times. Please remove the duplicate import`

If you do want to use loadSound in async code, this is how you should do it, FYI:

```auto
function setup() {
	noCanvas();
	notASketch();
}

async function notASketch() {
	// This is how you turn a function that takes callbacks into a promise:
	let loadSoundPromise = new Promise((resolve, reject) => loadSound('DING.WAV', resolve, reject));
	try {
		// Note: I created the Promise separately for clarity, but you could just inline it here.
		let ding = await loadSoundPromise;
		
		// This is always true, just here for demonstration purposes.
		if (ding.isLoaded()) {
			console.log('DING!');
		} else {
			console.warn(':-(');
		}
	} catch (e) {
		console.warn('loading failed.');
		console.error(e.message + '\n' + e.stack);
	}
}

```

However, keep in mind, you still can’t call this without first ensuring that `setup` has been called, because until `setup` is called there is no guarantee that `loadSound` will be declared yet.

---

<div class="post-metadata">

**Author:** ![micuat](https://yyz2.discourse-cdn.com/flex036/user_avatar/discourse.processing.org/micuat/32/19407_2.png) [@micuat](https://discourse.processing.org/u/micuat)\
**Post date:** [May 10, 2021, 9:00am UTC](https://discourse.processing.org/t/how-do-i-ensure-preload-has-finished/30006/6 "2021-05-10T09:00:05Z")

</div>

> [@whatsinausername](#):
>
> i tried cutting out as much irrelevant code as i could

just note that that is useful (as written in the guideline) while you should still keep the code runnable - posting a snippet (like you did) and posting a runnable, concise code are different things (and I prefer the latter).

I think KumuPaul’s answer is good - I think p5.js doesn’t have promise for `preload` (which is a bit problematic in some cases) but virtually you can use `setup` for that - because it ensures that `setup` is called after `preload` is done.

Another way can be, in phaser, simply skip the update loop until the audio file is loaded.

---

<div class="post-metadata">

**Author:** ![whatsinausername](https://avatars.discourse-cdn.com/v4/letter/w/e0b2c6/32.png) [@whatsinausername](https://discourse.processing.org/u/whatsinausername)\
**Post date:** [May 10, 2021, 3:22pm UTC](https://discourse.processing.org/t/how-do-i-ensure-preload-has-finished/30006/7 "2021-05-10T15:22:52Z")

</div>

thank you! that preload/setup code is exactly what i needed, and i appreciate the async example

---

<div class="post-metadata">

**Author:** ![whatsinausername](https://avatars.discourse-cdn.com/v4/letter/w/e0b2c6/32.png) [@whatsinausername](https://discourse.processing.org/u/whatsinausername)\
**Post date:** [May 10, 2021, 3:23pm UTC](https://discourse.processing.org/t/how-do-i-ensure-preload-has-finished/30006/8 "2021-05-10T15:23:45Z")

</div>

thank you for letting me know, i’ll post full runnable code next time 🙂
