diff --git a/README.md b/README.md index e01b8f9..b8f46e0 100644 --- a/README.md +++ b/README.md @@ -165,7 +165,11 @@ The `initProgressBar` function takes an optional object of options. The followin | resultElement | Override the *element* used for the result. If specified, resultElementId will be ignored. | document.getElementById(resultElementId) | | onProgress | function to call when progress is updated | CeleryProgressBar.onProgressDefault | | onSuccess | function to call when progress successfully completes | CeleryProgressBar.onSuccessDefault | -| onError | function to call when progress completes with an error | CeleryProgressBar.onErrorDefault | +| onError | function to call on a known error with no specified handler | CeleryProgressBar.onErrorDefault | +| onTaskError | function to call when progress completes with an error | onError | +| onNetworkError | function to call on a network error (ignored by WebSocket) | onError | +| onHttpError | function to call on a non-200 response (ignored by WebSocket) | onError | +| onDataError | function to call on a 200 response that's not JSON or has invalid schema due to a programming error (ignored by WebSocket) | onError | | onResult | function to call when returned non empty result | CeleryProgressBar.onResultDefault | diff --git a/celery_progress/static/celery_progress/celery_progress.js b/celery_progress/static/celery_progress/celery_progress.js index 85dbb44..e0a58d9 100644 --- a/celery_progress/static/celery_progress/celery_progress.js +++ b/celery_progress/static/celery_progress/celery_progress.js @@ -10,7 +10,11 @@ var CeleryProgressBar = (function () { } } - function onErrorDefault(progressBarElement, progressBarMessageElement, excMessage) { + /** + * Default handler for all errors. + * @param data - A Response object for HTTP errors, undefined for other errors + */ + function onErrorDefault(progressBarElement, progressBarMessageElement, excMessage, data) { progressBarElement.style.backgroundColor = '#dc4f63'; progressBarMessageElement.innerHTML = "Uh-Oh, something went wrong! " + excMessage; } @@ -22,7 +26,7 @@ var CeleryProgressBar = (function () { progressBarMessageElement.innerHTML = progress.current + ' of ' + progress.total + ' processed. ' + description; } - function updateProgress (progressUrl, options) { + async function updateProgress (progressUrl, options) { options = options || {}; var progressBarId = options.progressBarId || 'progress-bar'; var progressBarMessage = options.progressBarMessageId || 'progress-bar-message'; @@ -31,31 +35,53 @@ var CeleryProgressBar = (function () { var onProgress = options.onProgress || onProgressDefault; var onSuccess = options.onSuccess || onSuccessDefault; var onError = options.onError || onErrorDefault; + var onTaskError = options.onTaskError || onError; + var onNetworkError = options.onNetworkError || onError; + var onHttpError = options.onHttpError || onError; + var onDataError = options.onDataError || onError; var pollInterval = options.pollInterval || 500; var resultElementId = options.resultElementId || 'celery-result'; var resultElement = options.resultElement || document.getElementById(resultElementId); var onResult = options.onResult || onResultDefault; - fetch(progressUrl).then(function(response) { - response.json().then(function(data) { - if (data.progress) { - onProgress(progressBarElement, progressBarMessageElement, data.progress); - } - if (!data.complete) { - setTimeout(updateProgress, pollInterval, progressUrl, options); + let response; + try { + response = await fetch(progressUrl); + } catch (networkError) { + onNetworkError(progressBarElement, progressBarMessageElement, "Network Error"); + throw networkError; + } + + if (response.status === 200) { + let data; + try { + data = await response.json(); + } catch (parsingError) { + onDataError(progressBarElement, progressBarMessageElement, "Parsing Error") + throw parsingError; + } + + if (data.progress) { + onProgress(progressBarElement, progressBarMessageElement, data.progress); + } + if (data.complete === false) { + setTimeout(updateProgress, pollInterval, progressUrl, options); + } else { + if (data.success === true) { + onSuccess(progressBarElement, progressBarMessageElement, data.result); + } else if (data.success === false) { + onTaskError(progressBarElement, progressBarMessageElement, data.result); } else { - if (data.success) { - onSuccess(progressBarElement, progressBarMessageElement, data.result); - } else { - onError(progressBarElement, progressBarMessageElement, data.result); - } - if (data.result) { - onResult(resultElement, data.result); - } + onDataError(progressBarElement, progressBarMessageElement, "Data Error"); + } + if (data.hasOwnProperty('result')) { + onResult(resultElement, data.result); } - }); - }); + } + } else { + onHttpError(progressBarElement, progressBarMessageElement, "HTTP Code " + response.status, response); + } } return { onSuccessDefault: onSuccessDefault, diff --git a/celery_progress/static/celery_progress/websockets.js b/celery_progress/static/celery_progress/websockets.js index e136b03..6dfb78f 100644 --- a/celery_progress/static/celery_progress/websockets.js +++ b/celery_progress/static/celery_progress/websockets.js @@ -7,8 +7,8 @@ var CeleryWebSocketProgressBar = (function () { CeleryProgressBar.onResultDefault(resultElement, result); } - function onErrorDefault(progressBarElement, progressBarMessageElement, excMessage) { - CeleryProgressBar.onErrorDefault(progressBarElement, progressBarMessageElement, excMessage); + function onErrorDefault(progressBarElement, progressBarMessageElement, excMessage, data) { + CeleryProgressBar.onErrorDefault(progressBarElement, progressBarMessageElement, excMessage, data); } function onProgressDefault(progressBarElement, progressBarMessageElement, progress) { @@ -24,6 +24,7 @@ var CeleryWebSocketProgressBar = (function () { var onProgress = options.onProgress || onProgressDefault; var onSuccess = options.onSuccess || onSuccessDefault; var onError = options.onError || onErrorDefault; + var onTaskError = options.onTaskError || onError; var resultElementId = options.resultElementId || 'celery-result'; var resultElement = options.resultElement || document.getElementById(resultElementId); var onResult = options.onResult || onResultDefault; @@ -45,9 +46,9 @@ var CeleryWebSocketProgressBar = (function () { if (data.success) { onSuccess(progressBarElement, progressBarMessageElement, data.result); } else { - onError(progressBarElement, progressBarMessageElement, data.result); + onTaskError(progressBarElement, progressBarMessageElement, data.result); } - if (data.result) { + if (data.hasOwnProperty('result')) { onResult(resultElement, data.result); } ProgressSocket.close();