Skip to content

Loading retry improvements #6974

New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Open
wants to merge 7 commits into
base: master
Choose a base branch
from
4 changes: 1 addition & 3 deletions config/webpack.config.js
Original file line number Diff line number Diff line change
@@ -53,8 +53,6 @@ module.exports = [
});
}
}
],

devtool: 'source-map'
]
}
];
2 changes: 1 addition & 1 deletion src/core/Config.js
Original file line number Diff line number Diff line change
@@ -533,7 +533,7 @@ var Config = new Class({
/**
* @const {number} Phaser.Core.Config#loaderMaxRetries - The number of times to retry a file load if it fails.
*/
this.loaderMaxRetries = GetValue(config, 'loader.maxRetries', 2);
this.loaderMaxRetries = GetValue(config, 'loader.maxRetries', 5);

/**
* @const {boolean} Phaser.Core.Config#loaderWithCredentials - Optional XHR withCredentials value.
2 changes: 1 addition & 1 deletion src/core/typedefs/LoaderConfig.js
Original file line number Diff line number Diff line change
@@ -14,5 +14,5 @@
* @property {string[]} [localScheme] - An optional array of schemes that the Loader considers as being 'local' files. Defaults to: `[ 'file://', 'capacitor://' ]` if not specified.
* @property {boolean} [withCredentials=false] - Optional XHR withCredentials value.
* @property {string} [imageLoadType='XHR'] - Optional load type for image, `XHR` is default, or `HTMLImageElement` for a lightweight way.
* @property {number} [maxRetries=2] - The number of times to retry the file load if it fails.
* @property {number} [maxRetries=5] - The number of times to retry the file load if it fails.
*/
41 changes: 28 additions & 13 deletions src/loader/File.js
Original file line number Diff line number Diff line change
@@ -243,23 +243,33 @@ var File = new Class({
this.base64 = (typeof url === 'string') && (url.indexOf('data:') === 0);

/**
* The counter for the number of times to retry loading this file before it fails.
*
* The number of times to retry loading this file if it fails.
*
* You can set this property value in the FileConfig object. If not present,
* this property is read from the `LoaderPlugin.maxRetries` property when
* this File instance is created.
*
*
* You can set this value via the Game Config, or you can adjust the `LoaderPlugin` property
* at any point after the Loader has started. However, it will not apply to files
* that have already been added to the Loader, only those added after this value
* is changed.
*
* @name Phaser.Loader.File#retryAttempts
* @name Phaser.Loader.File#maxRetries
* @type {number}
* @default 5
* @since 3.88.0
*/
this.maxRetries = GetFastValue(this.xhrSettings, 'maxRetries', loader.maxRetries);

/**
* The counter for the number of times loading has failed and was retried.
*
* @name Phaser.Loader.File#retries
* @type {number}
* @default 2
* @since 3.85.0
* @default 0
* @since 3.88.0
*/
this.retryAttempts = GetFastValue(fileConfig, 'maxRetries', loader.maxRetries);
this.retries = 0;
},

/**
@@ -358,7 +368,7 @@ var File = new Class({

this.resetXHR();

this.loader.nextFile(this, success);
this.loader.nextFile(this, success, event);
},

/**
@@ -386,24 +396,29 @@ var File = new Class({
* Called if the file errors while loading, is sent a DOM ProgressEvent.
*
* @method Phaser.Loader.File#onError
* @fires Phaser.Loader.Events#FILE_LOAD_RETRY
* @since 3.0.0
*
* @param {XMLHttpRequest} xhr - The XMLHttpRequest that caused this onload event.
* @param {ProgressEvent} event - The DOM ProgressEvent that resulted from this error.
*/
onError: function ()
onError: function (xhr, event)
{
this.resetXHR();

if (this.retryAttempts > 0)
if (this.retries < this.maxRetries)
{
this.retryAttempts--;
var retryDelay = Math.min(Math.pow(2, this.retries) * 100, 5000); // ms

this.retries++;

this.loader.emit(Events.FILE_LOAD_RETRY, this, event, this.retries);

this.load();
setTimeout(this.load.bind(this), retryDelay);
}
else
{
this.loader.nextFile(this, false);
this.loader.nextFile(this, false, event);
}
},

11 changes: 6 additions & 5 deletions src/loader/LoaderPlugin.js
Original file line number Diff line number Diff line change
@@ -349,18 +349,18 @@ var LoaderPlugin = new Class({

/**
* The number of times to retry loading a single file before it fails.
*
*
* This property is read by the `File` object when it is created and set to
* the internal property of the same name. It's not used by the Loader itself.
*
*
* You can set this value via the Game Config, or you can adjust this property
* at any point after the Loader has started. However, it will not apply to files
* that have already been added to the Loader, only those added after this value
* is changed.
*
* @name Phaser.Loader.LoaderPlugin#maxRetries
* @type {number}
* @default 2
* @default 5
* @since 3.85.0
*/
this.maxRetries = GetFastValue(sceneConfig, 'maxRetries', gameConfig.loaderMaxRetries);
@@ -1029,8 +1029,9 @@ var LoaderPlugin = new Class({
*
* @param {Phaser.Loader.File} file - The File that just finished loading, or errored during load.
* @param {boolean} success - `true` if the file loaded successfully, otherwise `false`.
* @param {Event | string} [event] - The Event that resulted from an error, if loading was not successful.
*/
nextFile: function (file, success)
nextFile: function (file, success, event)
{
// Has the game been destroyed during load? If so, bail out now.
if (!this.inflight)
@@ -1058,7 +1059,7 @@ var LoaderPlugin = new Class({

this._deleteQueue.set(file);

this.emit(Events.FILE_LOAD_ERROR, file);
this.emit(Events.FILE_LOAD_ERROR, file, event);

this.fileProcessComplete(file);
}
3 changes: 2 additions & 1 deletion src/loader/events/FILE_LOAD_ERROR_EVENT.js
Original file line number Diff line number Diff line change
@@ -7,7 +7,7 @@
/**
* The File Load Error Event.
*
* This event is dispatched by the Loader Plugin when a file fails to load.
* This event is dispatched by the Loader Plugin when a file fails to load without retry.
*
* Listen to it from a Scene using: `this.load.on('loaderror', listener)`.
*
@@ -16,5 +16,6 @@
* @since 3.0.0
*
* @param {Phaser.Loader.File} file - A reference to the File which errored during load.
* @param {Event | string} event - The Event that resulted from this error.
*/
module.exports = 'loaderror';
23 changes: 23 additions & 0 deletions src/loader/events/FILE_LOAD_RETRY_EVENT.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,23 @@
/**
* @author Richard Davey <rich@phaser.io>
* @author Pavle Goloskokovic <pgoloskokovic@gmail.com> (http://prunegames.com)
* @copyright 2013-2024 Phaser Studio Inc.
* @license {@link https://opensource.org/licenses/MIT|MIT License}
*/

/**
* The File Load Retry Event.
*
* This event is dispatched by the Loader Plugin when a file fails to load but will retry loading.
*
* Listen to it from a Scene using: `this.load.on('loadretry', listener)`.
*
* @event Phaser.Loader.Events#FILE_LOAD_RETRY
* @type {string}
* @since 3.88.0
*
* @param {Phaser.Loader.File} file - A reference to the File which errored during load, and is retrying.
* @param {ProgressEvent} event - The DOM ProgressEvent that resulted from this error.
* @param {number} retries - The number of times loading has failed and was retried.
*/
module.exports = 'loadretry';
2 changes: 1 addition & 1 deletion src/loader/events/FILE_PROGRESS_EVENT.js
Original file line number Diff line number Diff line change
@@ -16,7 +16,7 @@
* @type {string}
* @since 3.0.0
*
* @param {Phaser.Loader.File} file - A reference to the File which errored during load.
* @param {Phaser.Loader.File} file - A reference to the File which is loading.
* @param {number} percentComplete - A value between 0 and 1 indicating how 'complete' this file is.
*/
module.exports = 'fileprogress';
1 change: 1 addition & 0 deletions src/loader/events/index.js
Original file line number Diff line number Diff line change
@@ -14,6 +14,7 @@ module.exports = {
COMPLETE: require('./COMPLETE_EVENT'),
FILE_COMPLETE: require('./FILE_COMPLETE_EVENT'),
FILE_KEY_COMPLETE: require('./FILE_KEY_COMPLETE_EVENT'),
FILE_LOAD_RETRY: require('./FILE_LOAD_RETRY_EVENT'),
FILE_LOAD_ERROR: require('./FILE_LOAD_ERROR_EVENT'),
FILE_LOAD: require('./FILE_LOAD_EVENT'),
FILE_PROGRESS: require('./FILE_PROGRESS_EVENT'),
6 changes: 4 additions & 2 deletions src/loader/filetypes/HTML5AudioFile.js
Original file line number Diff line number Diff line change
@@ -87,8 +87,10 @@ var HTML5AudioFile = new Class({
*
* @method Phaser.Loader.FileTypes.HTML5AudioFile#onError
* @since 3.0.0
*
* @param {Event | string} event - The Event that resulted from this error.
*/
onError: function ()
onError: function (event)
{
for (var i = 0; i < this.data.length; i++)
{
@@ -98,7 +100,7 @@ var HTML5AudioFile = new Class({
audio.onerror = null;
}

this.loader.nextFile(this, false);
this.loader.nextFile(this, false, event);
},

/**
4 changes: 2 additions & 2 deletions src/loader/filetypes/ImageFile.js
Original file line number Diff line number Diff line change
@@ -178,9 +178,9 @@ var ImageFile = new Class({
_this.loader.nextFile(_this, true);
};

this.data.onerror = function ()
this.data.onerror = function (event)
{
_this.loader.nextFile(_this, false);
_this.loader.nextFile(_this, false, event);
};

this.data.src = this.src;
1 change: 0 additions & 1 deletion src/loader/typedefs/FileConfig.js

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

3 changes: 2 additions & 1 deletion src/loader/typedefs/XHRSettingsObject.js
Original file line number Diff line number Diff line change
@@ -12,5 +12,6 @@
* @property {(string|undefined)} [headerValue] - This value is used to populate the XHR `setRequestHeader` and is undefined by default.
* @property {(string|undefined)} [requestedWith] - This value is used to populate the XHR `setRequestHeader` and is undefined by default.
* @property {(string|undefined)} [overrideMimeType] - Provide a custom mime-type to use instead of the default.
* @property {boolean} [withCredentials=false] - The withCredentials property indicates whether or not cross-site Access-Control requests should be made using credentials such as cookies, authorization headers or TLS client certificates. Setting withCredentials has no effect on same-site requests.
* @property {boolean} [withCredentials=false] - The withCredentials property indicates whether cross-site Access-Control requests should be made using credentials such as cookies, authorization headers or TLS client certificates. Setting withCredentials has no effect on same-site requests.
* @property {number} [maxRetries=5] - The number of times to retry the file load if it fails.
*/