import defaultValue from "./defaultValue.js"; import defined from "./defined.js"; import formatError from "./formatError.js"; /** * Provides details about an error that occurred in an {@link ImageryProvider} or a {@link TerrainProvider}. * * @alias TileProviderError * @constructor * * @param {ImageryProvider|TerrainProvider} provider The imagery or terrain provider that experienced the error. * @param {String} message A message describing the error. * @param {Number} [x] The X coordinate of the tile that experienced the error, or undefined if the error * is not specific to a particular tile. * @param {Number} [y] The Y coordinate of the tile that experienced the error, or undefined if the error * is not specific to a particular tile. * @param {Number} [level] The level of the tile that experienced the error, or undefined if the error * is not specific to a particular tile. * @param {Number} [timesRetried=0] The number of times this operation has been retried. * @param {Error} [error] The error or exception that occurred, if any. */ function TileProviderError( provider, message, x, y, level, timesRetried, error ) { /** * The {@link ImageryProvider} or {@link TerrainProvider} that experienced the error. * @type {ImageryProvider|TerrainProvider} */ this.provider = provider; /** * The message describing the error. * @type {String} */ this.message = message; /** * The X coordinate of the tile that experienced the error. If the error is not specific * to a particular tile, this property will be undefined. * @type {Number} */ this.x = x; /** * The Y coordinate of the tile that experienced the error. If the error is not specific * to a particular tile, this property will be undefined. * @type {Number} */ this.y = y; /** * The level-of-detail of the tile that experienced the error. If the error is not specific * to a particular tile, this property will be undefined. * @type {Number} */ this.level = level; /** * The number of times this operation has been retried. * @type {Number} * @default 0 */ this.timesRetried = defaultValue(timesRetried, 0); /** * True if the failed operation should be retried; otherwise, false. The imagery or terrain provider * will set the initial value of this property before raising the event, but any listeners * can change it. The value after the last listener is invoked will be acted upon. * @type {Boolean} * @default false */ this.retry = false; /** * The error or exception that occurred, if any. * @type {Error} */ this.error = error; } /** * Handles an error in an {@link ImageryProvider} or {@link TerrainProvider} by raising an event if it has any listeners, or by * logging the error to the console if the event has no listeners. This method also tracks the number * of times the operation has been retried and will automatically retry if requested to do so by the * event listeners. * * @param {TileProviderError} previousError The error instance returned by this function the last * time it was called for this error, or undefined if this is the first time this error has * occurred. * @param {ImageryProvider|TerrainProvider} provider The imagery or terrain provider that encountered the error. * @param {Event} event The event to raise to inform listeners of the error. * @param {String} message The message describing the error. * @param {Number} x The X coordinate of the tile that experienced the error, or undefined if the * error is not specific to a particular tile. * @param {Number} y The Y coordinate of the tile that experienced the error, or undefined if the * error is not specific to a particular tile. * @param {Number} level The level-of-detail of the tile that experienced the error, or undefined if the * error is not specific to a particular tile. * @param {TileProviderError.RetryFunction} retryFunction The function to call to retry the operation. If undefined, the * operation will not be retried. * @param {Error} [errorDetails] The error or exception that occurred, if any. * @returns {TileProviderError} The error instance that was passed to the event listeners and that * should be passed to this function the next time it is called for the same error in order * to track retry counts. */ TileProviderError.handleError = function( previousError, provider, event, message, x, y, level, retryFunction, errorDetails ) { let error = previousError; if (!defined(previousError)) { error = new TileProviderError( provider, message, x, y, level, 0, errorDetails ); } else { error.provider = provider; error.message = message; error.x = x; error.y = y; error.level = level; error.retry = false; error.error = errorDetails; ++error.timesRetried; } if (event.numberOfListeners > 0) { event.raiseEvent(error); } else { console.log( `An error occurred in "${provider.constructor.name}": ${formatError( message )}` ); } if (error.retry && defined(retryFunction)) { retryFunction(); } return error; }; /** * Handles success of an operation by resetting the retry count of a previous error, if any. This way, * if the error occurs again in the future, the listeners will be informed that it has not yet been retried. * * @param {TileProviderError} previousError The previous error, or undefined if this operation has * not previously resulted in an error. */ TileProviderError.handleSuccess = function(previousError) { if (defined(previousError)) { previousError.timesRetried = -1; } }; /** * A function that will be called to retry the operation. * @callback TileProviderError.RetryFunction */ export default TileProviderError;