Debouncing the LMS API calls

This commit is contained in:
Jonathan Putney
2020-06-29 16:58:24 -04:00
parent 79a11c6dd5
commit 063029e0ad
4 changed files with 178 additions and 108 deletions

144
dist/scorm-again.js vendored

File diff suppressed because one or more lines are too long

File diff suppressed because one or more lines are too long

File diff suppressed because one or more lines are too long

View File

@@ -912,6 +912,31 @@ export default class BaseAPI {
'The storeData method has not been implemented'); 'The storeData method has not been implemented');
} }
/**
* A debounce function to throttle calls to LMS commit API
*
* @param {function} func
* @param {number} wait
* @param {boolean} immediate
* @return {function(...[*]=)}
* @private
*/
_debounce(func, wait, immediate = false) {
let timeout;
return function(...args) {
const later = () => {
timeout = null; // added this to set same behaviour as ES5
// eslint-disable-next-line no-invalid-this
if (!immediate) func.apply(this, args); // this is called conditionally, just like in the ES5 version
};
const callNow = immediate && !timeout;
clearTimeout(timeout);
timeout = setTimeout(later, wait);
// eslint-disable-next-line no-invalid-this
if (callNow) func.apply(this, args);
};
}
/** /**
* Send the request to the LMS * Send the request to the LMS
* @param {string} url * @param {string} url
@@ -919,65 +944,70 @@ export default class BaseAPI {
* @return {object} * @return {object}
*/ */
processHttpRequest(url: String, params) { processHttpRequest(url: String, params) {
const genericError = { const debounced = this._debounce(
'result': global_constants.SCORM_FALSE, function(url, params, settings, error_codes) {
'errorCode': this.#error_codes.GENERAL, const genericError = {
}; 'result': global_constants.SCORM_FALSE,
'errorCode': error_codes.GENERAL,
};
let result; let result;
if (!this.#settings.sendBeaconCommit) { if (!settings.sendBeaconCommit) {
const httpReq = new XMLHttpRequest(); const httpReq = new XMLHttpRequest();
httpReq.open('POST', url, this.#settings.asyncCommit); httpReq.open('POST', url, settings.asyncCommit);
try { try {
if (params instanceof Array) { if (params instanceof Array) {
httpReq.setRequestHeader('Content-Type', httpReq.setRequestHeader('Content-Type',
'application/x-www-form-urlencoded'); 'application/x-www-form-urlencoded');
httpReq.send(params.join('&')); httpReq.send(params.join('&'));
} else { } else {
httpReq.setRequestHeader('Content-Type', httpReq.setRequestHeader('Content-Type',
this.settings.commitRequestDataType); settings.commitRequestDataType);
httpReq.send(JSON.stringify(params)); httpReq.send(JSON.stringify(params));
} }
if (typeof this.settings.responseHandler === 'function') { if (typeof settings.responseHandler === 'function') {
result = this.settings.responseHandler(httpReq); result = settings.responseHandler(httpReq);
} else { } else {
result = JSON.parse(httpReq.responseText); result = JSON.parse(httpReq.responseText);
} }
} catch (e) { } catch (e) {
console.error(e); console.error(e);
return genericError; return genericError;
} }
} else { } else {
try { try {
const headers = { const headers = {
type: this.settings.commitRequestDataType, type: settings.commitRequestDataType,
}; };
let blob; let blob;
if (params instanceof Array) { if (params instanceof Array) {
blob = new Blob([params.join('&')], headers); blob = new Blob([params.join('&')], headers);
} else { } else {
blob = new Blob([JSON.stringify(params)], headers); blob = new Blob([JSON.stringify(params)], headers);
} }
result = {}; result = {};
if (navigator.sendBeacon(url, blob)) { if (navigator.sendBeacon(url, blob)) {
result.result = global_constants.SCORM_TRUE; result.result = global_constants.SCORM_TRUE;
} else { } else {
result.result = global_constants.SCORM_FALSE; result.result = global_constants.SCORM_FALSE;
result.errorCode = 101; result.errorCode = 101;
} }
} catch (e) { } catch (e) {
console.error(e); console.error(e);
return genericError; return genericError;
} }
} }
if (typeof result === 'undefined') { if (typeof result === 'undefined') {
return genericError; return genericError;
} }
return result; return result;
}, 5000);
return debounced(url, params, this.settings);
} }
/** /**