diff --git a/api/js/jsapi/egw_json.js b/api/js/jsapi/egw_json.js index 417065f58d..28ddf848eb 100644 --- a/api/js/jsapi/egw_json.js +++ b/api/js/jsapi/egw_json.js @@ -385,6 +385,98 @@ egw.extend('json', egw.MODULE_WND_LOCAL, function(_app, _wnd) _context, _async, _sender, this); }, + /** + * Do an AJAX call and get a javascript promise, which will be resolved with the returned data. + * + * egw.request() returns immediately with a Promise. The promise will be resolved with just the returned data, + * any other "piggybacked" responses will be handled by registered handlers. The data will also be passed to + * any registered data handlers (egw.data) before it is passed to your handler. + * + * To use: + * @example + * egw.request( + * "EGroupware\\Api\\Etemplate\\Widget\\Select::ajax_get_options", + * ["select-cat"] + * ) + * .then(function(data) { + * // Deal with the returned data here. data may be undefined if no data was returned. + * console.log("Here's the categories:",data); + * }); + * + * + * The return is a Promise, so multiple .then() can be chained in the usual ways: + * @example + * egw.request(...) + * .then(function(data) { + * if(debug) console.log("Requested data", data); + * } + * .then(function(data) { + * // Change the data for the rest of the chain + * if(typeof data === "undefined") return []; + * } + * .then(function(data) { + * // data is never undefined now, if it was before it's an empty array now + * for(let i = 0; i < data.length; i++) + * { + * ... + * } + * } + * + * + * You can also fire off multiple requests, and wait for them to all be answered: + * @example + * let first = egw.request(...); + * let second = egw.request(...); + * Promise.all([first, second]) + * .then(function(values) { + * console.log("First:", values[0], "Second:", values[1]); + * } + * + * + * @param {string} _menuaction + * @param {any[]} _parameters + * + * @return Promise + */ + request: function(_menuaction, _parameters) + { + let request = new json_request(_menuaction, _parameters, null, this, true, this, this); + let ajax_promise = request.sendRequest(); + + // This happens first, immediately + let resolvePromise = function(resolve, reject) { + // Bind to ajax response - this is called _after_ any other handling + ajax_promise.always(function(response, status, p) { + if(status !== "success") reject(); + + // The ajax request has completed, get just the data & pass it on + if(response && response.response) + { + for(let value of response.response) + { + if(value.type && value.type === "data" && typeof value.data !== "undefined") + { + // Data was packed in response + resolve(value.data); + } + else if (value && typeof value.type === "undefined" && typeof value.data === "undefined") + { + // Just raw data + resolve(value); + } + } + } + + // No data? Resolve the promise with nothing + resolve(); + }); + }; + + const myPromise = new Promise(resolvePromise); + + return myPromise; + }, + /** * Registers a new handler plugin. *