[FIX] web: Views: sequential lazy loading of libs
The views can specify js (and css) libraries to lazy load when
they are instantiated for the first time. The previous
implementation was too naive as it always loaded the specified
libraries in parallel. However, it may happen (e.g. gantt view)
that some of those libraries depend on other ones.
This commit implements a mechanism to handle libs dependencies
between each other. For instance, specifying:
js_libs: [
['a', 'b'],
['c'],
],
will load 'a' and 'b' in parallel, but wait for them to be
loaded before loading 'c'.
The new implementation still supports the old syntax. So,
js_libs: ['a', 'b', 'c'],
will load 'a', 'b' and 'c' in parallel.
This commit is contained in:
@@ -185,8 +185,24 @@ var AbstractView = Class.extend({
|
||||
*/
|
||||
_loadLibs: function () {
|
||||
var defs = [];
|
||||
_.each(this.config.js_libs, function (url) {
|
||||
defs.push(ajax.loadJS(url));
|
||||
var jsDefs;
|
||||
_.each(this.config.js_libs, function (urls) {
|
||||
if (typeof(urls) === 'string') {
|
||||
// js_libs is an array of urls: those urls can be loaded in
|
||||
// parallel
|
||||
defs.push(ajax.loadJS(urls));
|
||||
} else {
|
||||
// js_libs is an array of arrays of urls: those arrays of urls
|
||||
// must be loaded sequentially, but the urls inside each
|
||||
// sub-array can be loaded in parallel
|
||||
defs.push($.when.apply($, jsDefs).then(function () {
|
||||
jsDefs = [];
|
||||
_.each(urls, function (url) {
|
||||
jsDefs.push(ajax.loadJS(url));
|
||||
});
|
||||
return $.when.apply($, jsDefs);
|
||||
}));
|
||||
}
|
||||
});
|
||||
_.each(this.config.css_libs, function (url) {
|
||||
defs.push(ajax.loadCSS(url));
|
||||
|
||||
@@ -0,0 +1,106 @@
|
||||
odoo.define('web.abstract_view_tests', function (require) {
|
||||
"use strict";
|
||||
|
||||
var AbstractView = require('web.AbstractView');
|
||||
var ajax = require('web.ajax');
|
||||
var testUtils = require('web.test_utils');
|
||||
|
||||
var createAsyncView = testUtils.createAsyncView;
|
||||
|
||||
QUnit.module('Views', {
|
||||
beforeEach: function () {
|
||||
this.data = {
|
||||
fake_model: {
|
||||
fields: {},
|
||||
record: [],
|
||||
},
|
||||
};
|
||||
},
|
||||
}, function () {
|
||||
|
||||
QUnit.module('AbstractView');
|
||||
|
||||
QUnit.test('lazy loading of js libs (in parallel)', function (assert) {
|
||||
var done = assert.async();
|
||||
assert.expect(6);
|
||||
|
||||
var def = $.Deferred();
|
||||
var loadJS = ajax.loadJS;
|
||||
ajax.loadJS = function (url) {
|
||||
assert.step(url);
|
||||
return def.then(function () {
|
||||
assert.step(url + ' loaded');
|
||||
});
|
||||
};
|
||||
var View = AbstractView.extend({
|
||||
config: _.extend({}, AbstractView.prototype.config, {
|
||||
js_libs: ['a', 'b'],
|
||||
}),
|
||||
});
|
||||
createAsyncView({
|
||||
View: View,
|
||||
arch: '<fake/>',
|
||||
data: this.data,
|
||||
model: 'fake_model',
|
||||
}).then(function (view) {
|
||||
assert.verifySteps(['a', 'b', 'a loaded', 'b loaded'],
|
||||
"should wait for both libs to be loaded");
|
||||
ajax.loadJS = loadJS;
|
||||
view.destroy();
|
||||
done();
|
||||
});
|
||||
|
||||
assert.verifySteps(['a', 'b'],
|
||||
"both libs should be loaded in parallel");
|
||||
def.resolve();
|
||||
});
|
||||
|
||||
QUnit.test('lazy loading of js libs (sequentially)', function (assert) {
|
||||
var done = assert.async();
|
||||
assert.expect(10);
|
||||
|
||||
var defs = {
|
||||
a: $.Deferred(),
|
||||
b: $.Deferred(),
|
||||
c: $.Deferred(),
|
||||
};
|
||||
var loadJS = ajax.loadJS;
|
||||
ajax.loadJS = function (url) {
|
||||
assert.step(url);
|
||||
return defs[url].then(function () {
|
||||
assert.step(url + ' loaded');
|
||||
});
|
||||
};
|
||||
var View = AbstractView.extend({
|
||||
config: _.extend({}, AbstractView.prototype.config, {
|
||||
js_libs: [
|
||||
['a', 'b'],
|
||||
['c'],
|
||||
],
|
||||
}),
|
||||
});
|
||||
createAsyncView({
|
||||
View: View,
|
||||
arch: '<fake/>',
|
||||
data: this.data,
|
||||
model: 'fake_model',
|
||||
}).then(function (view) {
|
||||
assert.verifySteps(['a', 'b', 'a loaded', 'b loaded', 'c', 'c loaded'],
|
||||
"should for all libs to be loaded");
|
||||
ajax.loadJS = loadJS;
|
||||
view.destroy();
|
||||
done();
|
||||
});
|
||||
|
||||
assert.verifySteps(['a', 'b'],
|
||||
"libs 'a' and 'b' should be loaded in parallel");
|
||||
defs.a.resolve();
|
||||
assert.verifySteps(['a', 'b', 'a loaded'],
|
||||
"should wait for 'a' and 'b' to be loaded before loading 'c'");
|
||||
defs.b.resolve();
|
||||
assert.verifySteps(['a', 'b', 'a loaded', 'b loaded', 'c'],
|
||||
"should load 'c' when 'a' and 'b' are loaded");
|
||||
defs.c.resolve();
|
||||
});
|
||||
});
|
||||
});
|
||||
@@ -434,6 +434,7 @@
|
||||
<script type="text/javascript" src="/web/static/tests/fields/relational_fields_tests.js"></script>
|
||||
<script type="text/javascript" src="/web/static/tests/fields/special_fields.js"></script>
|
||||
|
||||
<script type="text/javascript" src="/web/static/tests/views/abstract_view_tests.js"></script>
|
||||
<script type="text/javascript" src="/web/static/tests/views/form_tests.js"></script>
|
||||
<script type="text/javascript" src="/web/static/tests/views/graph_tests.js"></script>
|
||||
<script type="text/javascript" src="/web/static/tests/views/list_tests.js"></script>
|
||||
|
||||
Reference in New Issue
Block a user