diff options
| author | Vincent Schippefilt <vsc@odoo.com> | 2019-03-06 14:02:32 +0100 |
|---|---|---|
| committer | Aaron Bohy <aab@odoo.com> | 2019-03-06 20:07:17 +0100 |
| commit | ab56e637b7f97ddcdbcc9baea99ae097e342409c (patch) | |
| tree | 4cb47da9f7ef89b19d18429220a7507470ec12a9 /addons/web/static/src/js/core/ajax.js | |
| parent | eeed894fd50e477135e1ac9a82f6e98ce063ab90 (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.js | 325 |
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 = { |
