From 38ff63f778945fbe32aff17f9654a5cc863b03f4 Mon Sep 17 00:00:00 2001 From: nathangray Date: Fri, 16 Oct 2020 10:32:51 -0600 Subject: [PATCH] Api: New JavaScript API method egw.request(menuaction : string, parameters : any[]) : Promise Does an AJAX request, and resolves the returned Promise with just the data (no piggybacks) when it arrives from the server. Any registered data handlers are run before resolving the Promise. --- api/js/jsapi/egw_json.js | 92 ++++++++++++++++++++++++++++++++++++++++ 1 file changed, 92 insertions(+) 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. *