P5.js: question: how to load a json file in preload only if it exists

Created on 20 Dec 2018  路  10Comments  路  Source: processing/p5.js

Tried this with with a try/catch in preload and got the error below, after which the sketch hangs on 'Loading'. Might be nice if there was a way to load, for example, a .json config file in preload (without being forced to use the callback version of loadJSON) and have the sketch continue if its not there...

> p5.js says: It looks like there was a problem loading your json. Try checking if the file path [config.json] is correct, or running a local server.[https://github.com/processing/p5.js/wiki/Local-server]
p5.js:62653 Uncaught (in promise) Error: [object Object]
    at p5.js:62653
question

All 10 comments

Does it block execution? Does it show with p5.min.js? Is the error callback called when file is not present?

The first message looks like something FES throws. The second message is it coming from this line?

With both minified and non-minified v0.7.2 the sketch will hang in preload if the json file is not found, even if surrounded by a try/catch (as you suggest, the error above only shows with FES enabled). When a callback function is provided, things do work correctly. So not a big problem, as there is a workaround, but perhaps should be documented at least.

i'm not sure if this is intentional or not, but i think it's because the _decrementPreload() function is only called in the 'success' callback that's passed to httpDo by loadJSON.

https://github.com/processing/p5.js/blob/1f1463217982fc1ec9416ea370476d4f98597342/src/io/files.js#L155-L164
if we want failure to also progress to setup(), then i think the 'error' callback also needs to call _decrementPreload.


on a completely separate note. i noticed that the error behavior is different for these functions calling httpDo. some of them just call console.error(err):

https://github.com/processing/p5.js/blob/1f1463217982fc1ec9416ea370476d4f98597342/src/io/files.js#L578

... and others throw err:

https://github.com/processing/p5.js/blob/1f1463217982fc1ec9416ea370476d4f98597342/src/io/files.js#L172

I think this is intentional behaviour because when you are loading a file in preload without error callbacks the rest of the sketch code may be expecting sucessful load of the file if they are executed. If the sketch proceeds from preload even if it is a 404 the rest of the sketch may just error out itself expecting a file to have already been loaded.

@Spongman The inconsistency probably is due to some legacy code mixed with new code. It probably should be thrown to halt execution.

Is there a reason not to throw an error for the preload case, which the user could catch in the admittedly rare case where this was useful? Sketch would still terminate normally if not caught..

the problem is that the throw doesn't occur until after the loadXXX call returns (it happens during the callback). so there's no opportunity to catch. in addition, for this reason, i don't think it makes sense to throw in the httpDo callbacks. there's no user code that can catch that exception, and setup won't get called anyway, since _decrementPreload() won't have been called in that if-branch.

I don't think we can reasonably achieve this in the current setup.
You can do this:

let a;
function preload() {
  a = loadJSON(url, () => {}, () => this._decrementPreload());
}

But obviously _decrementPreload is internal and should not really be used in this manner.

@Spongman you are right that throwing in those callbacks is a bit strange - mostly they just cause an uncaught promise rejection, which in most browsers is just ignored. I converted some of these to console.error already when I noticed there were some throwing and some using console.error.

This issue has implications for the promised-based revamp of this loading system (#2698) and so I'm interested in how we would want this to work going forward. In particular, we've yet to find a suitably beginner-friendly way to support preloading blocking execution that isn't confusing. Alternatively, if we had support for async setup (#3000) then you could just do preload in there and control when you resolve:

let a;
async function setup() {
  try {
    a = await loadJSONAsync(url); // This is not implemented yet
  } catch (e) {}
}

Or with current fns:

let a;
async function setup() {
  try {
    a = await new Promise((resolve, reject) => loadJSON(url, resolve, reject));
  } catch (e) {}
}

i'm strongly in favor of the await loadXXXAsync in an async setup.

let loadJSONAsync = (url) => new Promise((resolve, reject) => loadJSON(url, resolve, reject));

I think eventually we will want to move to better support promise based loadXXX functions, to be able to use it with async/await is great in terms of beginner friendlyness but from what I see this is still pretty low priority even for the library code base update to ES6.

closing this because it is as @limzykenneth points out intended behavior and I believe difficult to implement with the current system.

Was this page helpful?
0 / 5 - 0 ratings

Related issues

Ongshu777 picture Ongshu777  路  24Comments

shiffman picture shiffman  路  56Comments

olleicua picture olleicua  路  22Comments

lmccart picture lmccart  路  49Comments

workergnome picture workergnome  路  32Comments