summaryrefslogtreecommitdiff
path: root/addons/web/static/src/js/core/ajax.js
diff options
context:
space:
mode:
authorVincent Schippefilt <vsc@odoo.com>2019-03-06 14:02:32 +0100
committerAaron Bohy <aab@odoo.com>2019-03-06 20:07:17 +0100
commitab56e637b7f97ddcdbcc9baea99ae097e342409c (patch)
tree4cb47da9f7ef89b19d18429220a7507470ec12a9 /addons/web/static/src/js/core/ajax.js
parenteeed894fd50e477135e1ac9a82f6e98ce063ab90 (diff)
[REF] web: adapt code after jQuery update
Part of task 1896658 Co-authored-by: Aaron Bohy <aab@odoo.com> Co-authored-by: Christophe Matthieu <chm@odoo.com> Co-authored-by: Mathieu Duckerts-Antoine <dam@odoo.com> Co-authored-by: David Monjoie <dmo@odoo.com> Co-authored-by: Martin Geubelle <mge@odoo.com> Co-authored-by: svs-odoo <svs@odoo.com> Co-authored-by: Vincent Schippefilt <vsc@odoo.com>
Diffstat (limited to 'addons/web/static/src/js/core/ajax.js')
-rw-r--r--addons/web/static/src/js/core/ajax.js325
1 files changed, 155 insertions, 170 deletions
diff --git a/addons/web/static/src/js/core/ajax.js b/addons/web/static/src/js/core/ajax.js
index 509126498bc..8e7216c7b00 100644
--- a/addons/web/static/src/js/core/ajax.js
+++ b/addons/web/static/src/js/core/ajax.js
@@ -3,22 +3,19 @@ odoo.define('web.ajax', function (require) {
var config = require('web.config');
var core = require('web.core');
-var utils = require('web.utils');
var time = require('web.time');
var download = require('web.download');
var contentdisposition = require('web.contentdisposition');
var _t = core._t;
-function genericJsonRpc (fct_name, params, settings, fct) {
+function _genericJsonRpc (fct_name, params, settings, fct) {
var shadow = settings.shadow || false;
delete settings.shadow;
if (!shadow) {
core.bus.trigger('rpc_request');
}
- var deferred = $.Deferred();
-
var data = {
jsonrpc: "2.0",
method: fct_name,
@@ -26,7 +23,7 @@ function genericJsonRpc (fct_name, params, settings, fct) {
id: Math.floor(Math.random() * 1000 * 1000 * 1000)
};
var xhr = fct(data);
- var result = xhr.pipe(function(result) {
+ var result = xhr.then(function(result) {
core.bus.trigger('rpc:result', data, result);
if (result.error !== undefined) {
if (result.error.data.arguments[0] !== "bus.Bus not available in test mode") {
@@ -36,65 +33,86 @@ function genericJsonRpc (fct_name, params, settings, fct) {
console.error("Server application error", JSON.stringify(result.error));
}
}
- return $.Deferred().reject("server", result.error);
+ return Promise.reject({type: "server", error: result.error});
} else {
return result.result;
}
}, function() {
//console.error("JsonRPC communication error", _.toArray(arguments));
- var def = $.Deferred();
- return def.reject.apply(def, ["communication"].concat(_.toArray(arguments)));
+ var reason = {
+ type: 'communication',
+ error: arguments[0],
+ textStatus: arguments[1],
+ errorThrown: arguments[2],
+ };
+ return Promise.reject(reason);
});
- deferred.abort = function () {
- deferred.reject({message: "XmlHttpRequestError abort"}, $.Event('abort'));
- if (xhr.abort) {
- xhr.abort();
- }
- };
- result.then(function (result) {
- if (!shadow) {
- core.bus.trigger('rpc_response');
- }
- deferred.resolve(result);
- }, function (type, error, textStatus, errorThrown) {
- if (type === "server") {
+ var rejection;
+ var promise = new Promise(function (resolve, reject) {
+ rejection = reject;
+
+ result.then(function (result) {
if (!shadow) {
core.bus.trigger('rpc_response');
}
- if (error.code === 100) {
- core.bus.trigger('invalidate_session');
- }
- deferred.reject(error, $.Event());
- } else {
- if (!shadow) {
- core.bus.trigger('rpc_response_failed');
+ resolve(result);
+ }, function (reason) {
+ var type = reason.type;
+ var error = reason.error;
+ var textStatus = reason.textStatus;
+ var errorThrown = reason.errorThrown;
+ if (type === "server") {
+ if (!shadow) {
+ core.bus.trigger('rpc_response');
+ }
+ if (error.code === 100) {
+ core.bus.trigger('invalidate_session');
+ }
+ reject({message: error, event: $.Event()});
+ } else {
+ if (!shadow) {
+ core.bus.trigger('rpc_response_failed');
+ }
+ var nerror = {
+ code: -32098,
+ message: "XmlHttpRequestError " + errorThrown,
+ data: {
+ type: "xhr"+textStatus,
+ debug: error.responseText,
+ objects: [error, errorThrown]
+ },
+ };
+ reject({message: nerror, event: $.Event()});
}
- var nerror = {
- code: -32098,
- message: "XmlHttpRequestError " + errorThrown,
- data: {
- type: "xhr"+textStatus,
- debug: error.responseText,
- objects: [error, errorThrown]
- },
- };
- deferred.reject(nerror, $.Event());
- }
+ });
});
- deferred.fail(function () { // Allow deferred user to disable rpc_error call in fail
- deferred.fail(function (error, event) {
- if (!event.isDefaultPrevented()) {
- core.bus.trigger('rpc_error', error, event);
- }
+
+ // FIXME: jsonp?
+ promise.abort = function () {
+ rejection({
+ message: "XmlHttpRequestError abort",
+ event: $.Event('abort')
});
+ if (xhr.abort) {
+ xhr.abort();
+ }
+ };
+ promise.guardedCatch(function (reason) { // Allow promise user to disable rpc_error call in case of failure
+ setTimeout(function () {
+ // we want to execute this handler after all others (hence
+ // setTimeout) to let the other handlers prevent the event
+ if (!reason.event.isDefaultPrevented()) {
+ core.bus.trigger('rpc_error', reason.message, reason.event);
+ }
+ }, 0);
});
- return deferred;
-}
+ return promise;
+};
function jsonRpc(url, fct_name, params, settings) {
settings = settings || {};
- return genericJsonRpc(fct_name, params, settings, function(data) {
+ return _genericJsonRpc(fct_name, params, settings, function(data) {
return $.ajax(url, _.extend({}, settings, {
url: url,
dataType: 'json',
@@ -110,19 +128,6 @@ function rpc(url, params, settings) {
return jsonRpc(url, 'call', params, settings);
}
-// helper
-function realSetTimeout (fct, millis) {
- var finished = new Date().getTime() + millis;
- var wait = function() {
- var current = new Date().getTime();
- if (current < finished) {
- setTimeout(wait, finished - current);
- } else {
- fct();
- }
- };
- setTimeout(wait, millis);
-}
/**
* Load css asynchronously: fetch it from the url parameter and add a link tag
@@ -131,26 +136,27 @@ function realSetTimeout (fct, millis) {
* immediately.
*
* @param {String} url of the css to be fetched
- * @returns {Deferred} resolved when the css has been loaded.
+ * @returns {Promise} resolved when the css has been loaded.
*/
var loadCSS = (function () {
- var urlDefs = Object.create(null);
+ var urlDefs = {};
return function loadCSS(url) {
if (url in urlDefs) {
// nothing to do here
} else if ($('link[href="' + url + '"]').length) {
- // the link is already in the DOM, the deferred can be resolved
- urlDefs[url] = $.when();
+ // the link is already in the DOM, the promise can be resolved
+ urlDefs[url] = Promise.resolve();
} else {
var $link = $('<link>', {
'href': url,
'rel': 'stylesheet',
'type': 'text/css'
});
- urlDefs[url] = $.Deferred();
- $link.on('load', function () {
- urlDefs[url].resolve();
+ urlDefs[url] = new Promise(function (resolve, reject) {
+ $link.on('load', function () {
+ resolve();
+ });
});
$('head').append($link);
}
@@ -159,44 +165,45 @@ var loadCSS = (function () {
})();
var loadJS = (function () {
- var urls = [];
- var defs = [];
+ var dependenciesPromise = {};
var load = function loadJS(url) {
// Check the DOM to see if a script with the specified url is already there
var alreadyRequired = ($('script[src="' + url + '"]').length > 0);
- // If loadJS was already called with the same URL, it will have a registered deferred indicating if
- // the script has been fully loaded. If not, the deferred has to be initialized. This is initialized
- // as already resolved if the script was already there without the need of loadJS.
- var index = _.indexOf(urls, url);
- if (index < 0) {
- urls.push(url);
- index = defs.push(alreadyRequired ? $.when() : $.Deferred()) - 1;
+ // If loadJS was already called with the same URL, it will have a registered promise indicating if
+ // the script has been fully loaded. If not, the promise has to be initialized.
+ // This is initialized as already resolved if the script was already there without the need of loadJS.
+ if (url in dependenciesPromise) {
+ return dependenciesPromise[url];
}
+ var scriptLoadedPromise = new Promise(function (resolve, reject) {
+ if (alreadyRequired) {
+ resolve();
+ } else {
+ // Get the script associated promise and returns it after initializing the script if needed. The
+ // promise is marked to be resolved on script load and rejected on script error.
+ var script = document.createElement('script');
+ script.type = 'text/javascript';
+ script.src = url;
+ script.onload = script.onreadystatechange = function() {
+ if ((script.readyState && script.readyState !== "loaded" && script.readyState !== "complete") || script.onload_done) {
+ return;
+ }
+ script.onload_done = true;
+ resolve(url);
+ };
+ script.onerror = function () {
+ console.error("Error loading file", script.src);
+ reject(url);
+ };
+ var head = document.head || document.getElementsByTagName('head')[0];
+ head.appendChild(script);
+ }
+ });
- // Get the script associated deferred and returns it after initializing the script if needed. The
- // deferred is marked to be resolved on script load and rejected on script error.
- var def = defs[index];
- if (!alreadyRequired) {
- var script = document.createElement('script');
- script.type = 'text/javascript';
- script.src = url;
- script.onload = script.onreadystatechange = function() {
- if ((script.readyState && script.readyState !== "loaded" && script.readyState !== "complete") || script.onload_done) {
- return;
- }
- script.onload_done = true;
- def.resolve(url);
- };
- script.onerror = function () {
- console.error("Error loading file", script.src);
- def.reject(url);
- };
- var head = document.head || document.getElementsByTagName('head')[0];
- head.appendChild(script);
- }
- return def;
+ dependenciesPromise[url] = scriptLoadedPromise;
+ return scriptLoadedPromise;
};
return load;
@@ -308,22 +315,6 @@ function get_file(options) {
}
function post (controller_url, data) {
-
- var progressHandler = function (deferred) {
- return function (state) {
- if(state.lengthComputable) {
- deferred.notify({
- h_loaded: utils.human_size(state.loaded),
- h_total : utils.human_size(state.total),
- loaded : state.loaded,
- total : state.total,
- pcent : Math.round((state.loaded/state.total)*100)
- });
- }
- };
- };
-
- var Def = $.Deferred();
var postData = new FormData();
$.each(data, function(i,val) {
@@ -333,25 +324,20 @@ function post (controller_url, data) {
postData.append('csrf_token', core.csrf_token);
}
- var xhr = new XMLHttpRequest();
- if(xhr.upload) xhr.upload.addEventListener('progress', progressHandler(Def), false);
-
- var ajaxDef = $.ajax(controller_url, {
- xhr: function() {return xhr;},
- data: postData,
- processData: false,
- contentType: false,
- type: 'POST'
- }).then(function (data) {Def.resolve(data);})
- .fail(function (data) {Def.reject(data);});
-
- return Def;
+ return new Promise(function (resolve, reject) {
+ $.ajax(controller_url, {
+ data: postData,
+ processData: false,
+ contentType: false,
+ type: 'POST'
+ }).then(resolve).fail(reject);
+ });
}
/**
* Loads an XML file according to the given URL and adds its associated qweb
* templates to the given qweb engine. The function can also be used to get
- * the deferred which indicates when all the calls to the function are finished.
+ * the promise which indicates when all the calls to the function are finished.
*
* Note: "all the calls" = the calls that happened before the current no-args
* one + the calls that will happen after but when the previous ones are not
@@ -359,8 +345,8 @@ function post (controller_url, data) {
*
* @param {string} [url] - an URL where to find qweb templates
* @param {QWeb} [qweb] - the engine to which the templates need to be added
- * @returns {Deferred}
- * If no argument is given to the function, the deferred's state
+ * @returns {Promise}
+ * If no argument is given to the function, the promise's state
* indicates if "all the calls" are finished (see main description).
* Otherwise, it indicates when the templates associated to the given
* url have been loaded.
@@ -369,63 +355,64 @@ var loadXML = (function () {
// Some "static" variables associated to the loadXML function
var isLoading = false;
var loadingsData = [];
- var allLoadingsDef = $.when();
var seenURLs = [];
return function (url, qweb) {
- // If no argument, simply returns the deferred which indicates when
+ function _load() {
+ isLoading = true;
+ if (loadingsData.length) {
+ // There is something to load, load it, resolve the associated
+ // promise then start loading the next one
+ var loadingData = loadingsData[0];
+ loadingData.qweb.add_template(loadingData.url, function () {
+ // Remove from array only now so that multiple calls to
+ // loadXML with the same URL returns the right promise
+ loadingsData.shift();
+ loadingData.resolve();
+ _load();
+ });
+ } else {
+ // There is nothing to load anymore, so resolve the
+ // "all the calls" promise
+ isLoading = false;
+ }
+ }
+
+ // If no argument, simply returns the promise which indicates when
// "all the calls" are finished
if (!url || !qweb) {
- return allLoadingsDef;
+ return Promise.resolve();
}
// If the given URL has already been seen, do nothing but returning the
- // associated deferred
+ // associated promise
if (_.contains(seenURLs, url)) {
var oldLoadingData = _.findWhere(loadingsData, {url: url});
- return oldLoadingData ? oldLoadingData.def : $.when();
+ return oldLoadingData ? oldLoadingData.def : Promise.resolve();
}
seenURLs.push(url);
+
// Add the information about the new data to load: the url, the qweb
- // engine and the associated deferred
+ // engine and the associated promise
var newLoadingData = {
url: url,
qweb: qweb,
- def: $.Deferred(),
};
+ newLoadingData.def = new Promise(function (resolve, reject) {
+ newLoadingData.resolve = resolve;
+ newLoadingData.reject = reject;
+ });
loadingsData.push(newLoadingData);
// If not already started, start the loading loop (reinitialize the
- // "all the calls" deferred to an unresolved state)
+ // "all the calls" promise to an unresolved state)
if (!isLoading) {
- allLoadingsDef = $.Deferred();
_load();
}
- // Return the deferred associated to the new given URL
+ // Return the promise associated to the new given URL
return newLoadingData.def;
-
- function _load() {
- isLoading = true;
- if (loadingsData.length) {
- // There is something to load, load it, resolve the associated
- // deferred then start loading the next one
- var loadingData = loadingsData[0];
- loadingData.qweb.add_template(loadingData.url, function () {
- // Remove from array only now so that multiple calls to
- // loadXML with the same URL returns the right deferred
- loadingsData.shift();
- loadingData.def.resolve();
- _load();
- });
- } else {
- // There is nothing to load anymore, so resolve the
- // "all the calls" deferred
- isLoading = false;
- allLoadingsDef.resolve();
- }
- }
};
})();
@@ -444,7 +431,7 @@ var loadAsset = (function () {
var load = function loadAsset(xmlId) {
if (cache[xmlId]) {
- return $.when(cache[xmlId]);
+ return Promise.resolve(cache[xmlId]);
}
var params = {
args: [xmlId, {
@@ -493,22 +480,20 @@ var loadAsset = (function () {
* @param {Array<string>} [libs.assetLibs=[]] A list of xmlId. The loaded template
* contains the script and link to be loaded
*
- * @returns {Deferred}
+ * @returns {Promise}
*/
function loadLibs (libs) {
var defs = [];
- _.each(libs.jsLibs || [], function (urls) {
- defs.push($.when.apply($, defs).then(function () {
+ (libs.jsLibs || []).forEach(function (urls) {
+ defs.push(Promise.all(defs).then(function () {
if (typeof(urls) === 'string') {
return ajax.loadJS(urls);
} else {
- return $.when.apply($, _.map(urls, function (url) {
- return ajax.loadJS(url);
- }));
+ return Promise.all(urls.map(ajax.loadJS));
}
}));
});
- _.each(libs.cssLibs || [], function (url) {
+ (libs.cssLibs || []).forEach(function (url) {
defs.push(ajax.loadCSS(url));
});
_.each(libs.assetLibs || [], function (xmlId) {
@@ -516,7 +501,7 @@ function loadLibs (libs) {
return loadLibs(asset);
}));
});
- return $.when.apply($, defs);
+ return Promise.all(defs);
}
var ajax = {