fix async loading caused app.js not being loaded before et2.load() tried to instantiate it

This commit is contained in:
Ralf Becker 2021-06-08 17:13:30 +02:00
parent 8fa2bb466b
commit bfea641321
7 changed files with 35 additions and 87 deletions

View File

@ -374,10 +374,15 @@ export class etemplate2 {
} }
var start_time = (new Date).getTime(); var start_time = (new Date).getTime();
} }
// require necessary translations from server, if not already loaded // require necessary translations from server AND the app.js file, if not already loaded
if (!jQuery.isArray(_data.langRequire)) if (!jQuery.isArray(_data.langRequire))
_data.langRequire = []; _data.langRequire = [];
egw(currentapp, window).langRequire(window, _data.langRequire, function () { Promise.all([
egw(currentapp, window).langRequire(window, _data.langRequire),
egw(currentapp, window).includeJS('/' + appname + '/js/app.js', undefined, undefined, egw.webserverUrl)
]).catch((err) => {
console.log("et2.load(): error loading lang-files and app.js: " + err.message);
}).then(() => {
this.clear(); this.clear();
// Initialize application js // Initialize application js
let app_callback = null; let app_callback = null;
@ -546,7 +551,7 @@ export class etemplate2 {
// Split the given data into array manager objects and pass those to the // Split the given data into array manager objects and pass those to the
// widget container - do this here because file is loaded async // widget container - do this here because file is loaded async
this._widgetContainer.setArrayMgrs(this._createArrayManagers(_data)); this._widgetContainer.setArrayMgrs(this._createArrayManagers(_data));
}, this); });
} }
/** /**
* Check if template contains any dirty (unsaved) content * Check if template contains any dirty (unsaved) content

View File

@ -563,10 +563,14 @@ export class etemplate2
var start_time = (new Date).getTime(); var start_time = (new Date).getTime();
} }
// require necessary translations from server, if not already loaded // require necessary translations from server AND the app.js file, if not already loaded
if (!jQuery.isArray(_data.langRequire)) _data.langRequire = []; if (!jQuery.isArray(_data.langRequire)) _data.langRequire = [];
egw(currentapp, window).langRequire(window, _data.langRequire, function () Promise.all([
{ egw(currentapp, window).langRequire(window, _data.langRequire),
egw(currentapp, window).includeJS('/'+appname+'/js/app.js', undefined, undefined, egw.webserverUrl)
]).catch((err) => {
console.log("et2.load(): error loading lang-files and app.js: "+err.message);
}).then(() => {
this.clear(); this.clear();
// Initialize application js // Initialize application js
@ -784,7 +788,7 @@ export class etemplate2
// Split the given data into array manager objects and pass those to the // Split the given data into array manager objects and pass those to the
// widget container - do this here because file is loaded async // widget container - do this here because file is loaded async
this._widgetContainer.setArrayMgrs(this._createArrayManagers(_data)); this._widgetContainer.setArrayMgrs(this._createArrayManagers(_data));
}, this); });
} }
/** /**

View File

@ -156,52 +156,22 @@ egw.extend('files', egw.MODULE_WND_LOCAL, function(_app, _wnd)
{ {
_jsFiles = [_jsFiles]; _jsFiles = [_jsFiles];
} }
const promise = Promise.all(_jsFiles.map((src) => import(_prefix ? _prefix+src : src))); let promise;
return typeof _callback === 'undefined' ? promise : promise.then(_callback.call(_context)); if (_jsFiles.length === 1) // running this in below case fails when loading app.js from etemplate.load()
// @todo check the prefix stuff
// LABjs uses prefix only if url is not absolute, so removing leading / if necessary and add it to prefix
if (_prefix)
{ {
for(var i=0; i < _jsFiles.length; ++i) const src = _jsFiles[0];
{ promise = import(_prefix ? _prefix+src : src);
if (_jsFiles[i].charAt(0) == '/') _jsFiles[i] = _jsFiles[i].substr(1);
} }
}
// as all our included checks use egw relative url strip off egw-url and use it as prefix
else else
{ {
_jsFiles = strip_egw_url(_jsFiles); promise = Promise.all(_jsFiles.map((src) => {
_prefix = egw.webserverUrl; import(_prefix ? _prefix+src : src)
.catch((err) => {
console.log(src+":\n\n"+err.message);
})
}));
} }
if (_prefix.charAt(_prefix.length-1) != '/') return typeof _callback === 'undefined' ? promise : promise.then(_callback.call(_context));
{
_prefix += '/';
}
// search and NOT load files already included as part of a bundle
for(var i=0; i < _jsFiles.length; ++i)
{
var file = _jsFiles[i];
if (this.included(file, true)) // check if included and marks as such if not
{
_jsFiles.splice(i, 1);
i--; // as index will be incr by for!
}
}
// check if all files already included or sheduled to be included --> call callback via egw_LAB.wait
if (!_jsFiles.length)
{
egw_LAB.wait(function(){
_callback.call(_context);
});
return;
}
// setting AlwaysPreserverOrder: true, 'til we have some other means of ensuring dependency resolution
(egw_LAB || $LAB.setOptions({AlwaysPreserveOrder:true,BasePath:_prefix})).script(_jsFiles).wait(function(){
_callback.call(_context);
});
}, },
/** /**

View File

@ -854,7 +854,7 @@ declare interface IegwWndLocal extends IegwGlobal
* @param {object} _context * @param {object} _context
* @param {string} _prefix prefix for _jsFiles * @param {string} _prefix prefix for _jsFiles
*/ */
includeJS(_jsFiles : string|string[], _callback : Function, _context? : object, _prefix? : string); includeJS(_jsFiles : string|string[], _callback? : Function, _context? : object, _prefix? : string);
/** /**
* Check if file is already included and optional mark it as included if not yet included * Check if file is already included and optional mark it as included if not yet included
* *

View File

@ -1,4 +1,4 @@
export var app = window.app; //export var app = window.app;
export var egw = window.egw; export var egw = window.egw;
export var framework = window.framework; export var framework = window.framework;
export var egw_get_file_editor_prefered_mimes = window.egw_get_file_editor_prefered_mimes; export var egw_get_file_editor_prefered_mimes = window.egw_get_file_editor_prefered_mimes;

View File

@ -521,17 +521,10 @@ egw.extend('json', egw.MODULE_WND_LOCAL, function(_app, _wnd)
// check if we need a not yet included app.js object --> include it now and return a Promise // check if we need a not yet included app.js object --> include it now and return a Promise
else if (i == 1 && parts[0] == 'app' && typeof app.classes[parts[1]] === 'undefined') else if (i == 1 && parts[0] == 'app' && typeof app.classes[parts[1]] === 'undefined')
{ {
const self = this; this.includeJS('/'+parts[1]+'/js/app.js', undefined, undefined, this.webserverUrl)
return new Promise(function(resolve, reject) .then(() => this.applyFunc(_func, args, _context));
{
// cache for a day, better then no invalidation
self.includeJS('/'+parts[1]+'/js/app.js?'+((new Date).valueOf()/86400|0).toString(), function ()
{
resolve(self.applyFunc(_func, args, _context));
}, self, self.webserverUrl);
});
} }
// check if we need a not yet instanciated app.js object --> instanciate it now // check if we need a not yet instantiated app.js object --> instantiate it now
else if (i == 1 && parts[0] == 'app' && typeof app.classes[parts[1]] === 'function') else if (i == 1 && parts[0] == 'app' && typeof app.classes[parts[1]] === 'function')
{ {
parent = parent[parts[1]] = new app.classes[parts[1]](); parent = parent[parts[1]] = new app.classes[parts[1]]();

View File

@ -134,7 +134,7 @@ egw.extend('lang', egw.MODULE_GLOBAL, function()
* } * }
* @param {function} _callback called after loading, if not given ready event will be postponed instead * @param {function} _callback called after loading, if not given ready event will be postponed instead
* @param {object} _context for callback * @param {object} _context for callback
* @return Promise if no _callback specified * @return Promise
*/ */
langRequire: function(_window, _apps, _callback, _context) { langRequire: function(_window, _apps, _callback, _context) {
// Get the ready and the files module for the given window // Get the ready and the files module for the given window
@ -161,32 +161,8 @@ egw.extend('lang', egw.MODULE_GLOBAL, function()
this.lang_order = apps.reverse(); this.lang_order = apps.reverse();
} }
// Only continue if we need to include a language const promise = files.includeJS(jss, _callback, _context || null);
if (jss.length > 0) return typeof _callback === 'function' ? promise.then(_callback.call(_context)) : promise;
{
if (typeof _callback == 'function')
{
files.includeJS(jss, _callback, _context || null);
}
else
{
// Require a "ready postpone token"
var token = ready.readyWaitFor();
return new Promise(function(resolve)
{
// Call "readyDone" once all js files have been included.
files.includeJS(jss, function () {
ready.readyDone(token);
resolve();
}, this);
});
}
}
else if (typeof _callback == 'function')
{
_callback.call(_context || null);
}
} }
}; };