mirror of
https://github.com/EGroupware/egroupware.git
synced 2024-12-24 15:48:55 +01:00
7a75f50362
Fixes callback was not called if response was []
207 lines
5.8 KiB
JavaScript
207 lines
5.8 KiB
JavaScript
/**
|
|
* EGroupware clientside API object
|
|
*
|
|
* @license http://opensource.org/licenses/gpl-license.php GPL - GNU General Public License
|
|
* @package etemplate
|
|
* @subpackage api
|
|
* @link http://www.egroupware.org
|
|
* @author Andreas Stöckel (as AT stylite.de)
|
|
* @author Ralf Becker <RalfBecker@outdoor-training.de>
|
|
*/
|
|
|
|
/*egw:uses
|
|
egw_core;
|
|
egw_debug;
|
|
*/
|
|
import './egw_core.js';
|
|
|
|
egw.extend('jsonq', egw.MODULE_GLOBAL, function()
|
|
{
|
|
"use strict";
|
|
|
|
/**
|
|
* Explicit registered push callbacks
|
|
*
|
|
* @type {Function[]}
|
|
*/
|
|
let push_callbacks = [];
|
|
|
|
/**
|
|
* Queued json requests (objects with attributes menuaction, parameters, context, callback, sender and callbeforesend)
|
|
*
|
|
* @access private, use jsonq method to queue requests
|
|
*/
|
|
const jsonq_queue = {};
|
|
|
|
/**
|
|
* Next uid (index) in queue
|
|
*/
|
|
let jsonq_uid = 0;
|
|
|
|
/**
|
|
* Running timer for next send of queued items
|
|
*/
|
|
let jsonq_timer = null;
|
|
|
|
/**
|
|
* Send the whole job-queue to the server in a single json request with menuaction=queue
|
|
*/
|
|
function jsonq_send()
|
|
{
|
|
if (jsonq_uid > 0 && typeof jsonq_queue['u'+(jsonq_uid-1)] == 'object')
|
|
{
|
|
const jobs_to_send = {};
|
|
let something_to_send = false;
|
|
for(let uid in jsonq_queue)
|
|
{
|
|
const job = jsonq_queue[uid];
|
|
|
|
if (job.menuaction === 'send') continue; // already send to server
|
|
|
|
// if job has a callbeforesend callback, call it to allow it to modify parameters
|
|
if (typeof job.callbeforesend === 'function')
|
|
{
|
|
job.callbeforesend.call(job.sender, job.parameters);
|
|
}
|
|
jobs_to_send[uid] = {
|
|
menuaction: job.menuaction,
|
|
parameters: job.parameters
|
|
};
|
|
job.menuaction = 'send';
|
|
job.parameters = null;
|
|
something_to_send = true;
|
|
}
|
|
if (something_to_send)
|
|
{
|
|
egw.request('api.queue', jobs_to_send).then(_data =>
|
|
{
|
|
if (typeof _data != 'object') throw "jsonq_callback called with NO object as parameter!";
|
|
|
|
const json = egw.json('none');
|
|
for(let uid in _data)
|
|
{
|
|
if (typeof jsonq_queue[uid] == 'undefined')
|
|
{
|
|
console.log("jsonq_callback received response for not existing queue uid="+uid+"!");
|
|
console.log(_data[uid]);
|
|
continue;
|
|
}
|
|
const job = jsonq_queue[uid];
|
|
const response = _data[uid];
|
|
|
|
// The ajax request has completed, get just the data & pass it on
|
|
if(response)
|
|
{
|
|
for(let value of response)
|
|
{
|
|
if(value.type && value.type === "data" && typeof value.data !== "undefined")
|
|
{
|
|
// Data was packed in response
|
|
job.resolve(value.data);
|
|
}
|
|
else if (value && typeof value.type === "undefined" && typeof value.data === "undefined")
|
|
{
|
|
// Just raw data
|
|
job.resolve(value);
|
|
}
|
|
else
|
|
{
|
|
// fake egw.json_request object, to call it with the current response
|
|
json.handleResponse({response: response});
|
|
}
|
|
}
|
|
// Response is there, but empty. Make sure to resolve it or the callback doesn't get called.
|
|
if (typeof response.length !== "undefined" && response.length == 0)
|
|
{
|
|
job.resolve();
|
|
}
|
|
}
|
|
|
|
delete jsonq_queue[uid];
|
|
}
|
|
// if nothing left in queue, stop interval-timer to give browser a rest
|
|
if (jsonq_timer && typeof jsonq_queue['u'+(jsonq_uid-1)] != 'object')
|
|
{
|
|
window.clearInterval(jsonq_timer);
|
|
jsonq_timer = null;
|
|
}
|
|
});
|
|
}
|
|
}
|
|
}
|
|
|
|
return {
|
|
/**
|
|
* Send a queued JSON call to the server
|
|
*
|
|
* @param {string} _menuaction the menuaction function which should be called and
|
|
* which handles the actual request. If the menuaction is a full featured
|
|
* url, this one will be used instead.
|
|
* @param {array} _parameters which should be passed to the menuaction function.
|
|
* @param {function|undefined} _callback callback function which should be called upon a "data" response is received
|
|
* @param {object|undefined} _sender is the reference object the callback function should get
|
|
* @param {function|undefined} _callbeforesend optional callback function which can modify the parameters, eg. to do some own queuing
|
|
* @return Promise
|
|
*/
|
|
jsonq: function(_menuaction, _parameters, _callback, _sender, _callbeforesend)
|
|
{
|
|
const uid = 'u'+(jsonq_uid++);
|
|
jsonq_queue[uid] = {
|
|
menuaction: _menuaction,
|
|
// IE JSON-serializes arrays passed in from different window contextx (eg. popups)
|
|
// as objects (it looses object-type of array), causing them to be JSON serialized
|
|
// as objects and loosing parameters which are undefined
|
|
// JSON.stringify([123,undefined]) --> '{"0":123}' instead of '[123,null]'
|
|
parameters: _parameters ? [].concat(_parameters) : [],
|
|
callbeforesend: _callbeforesend && _sender ? _callbeforesend.bind(_sender) : _callbeforesend,
|
|
};
|
|
let promise = new Promise(resolve => {
|
|
jsonq_queue[uid].resolve = resolve;
|
|
});
|
|
if (typeof _callback === 'function')
|
|
{
|
|
const callback = _callback.bind(_sender);
|
|
promise = promise.then(_data => {
|
|
callback(_data);
|
|
return _data;
|
|
});
|
|
}
|
|
|
|
if (jsonq_timer == null)
|
|
{
|
|
// check / send queue every N ms
|
|
jsonq_timer = window.setInterval(() => jsonq_send(), 100);
|
|
}
|
|
return promise;
|
|
},
|
|
|
|
/**
|
|
* Register a callback to receive push broadcasts eg. in a popup or iframe
|
|
*
|
|
* It's also used internally by egw_message's push method to dispatch to the registered callbacks.
|
|
*
|
|
* @param {Function|PushData} data callback (with bound context) or PushData to dispatch to callbacks
|
|
*/
|
|
registerPush: function(data)
|
|
{
|
|
if (typeof data === "function")
|
|
{
|
|
push_callbacks.push(data);
|
|
}
|
|
else
|
|
{
|
|
for (let n in push_callbacks)
|
|
{
|
|
try {
|
|
push_callbacks[n].call(this, data);
|
|
}
|
|
// if we get an exception, we assume the callback is no longer available and remove it
|
|
catch (ex) {
|
|
push_callbacks.splice(n, 1);
|
|
}
|
|
}
|
|
}
|
|
}
|
|
|
|
};
|
|
}); |