Dojo:使用 setTimeout 以异步方式加载小部件
Dojo: using setTimeout to load widgets in async way
假设我们有一个 Sequence
小部件,它加载 Element
个小部件并为每个小部件加载一些配置(通过 loadConfig()
)。示意图如下图所示:
问题是我尝试过的每一种方法都做同样的事情 "bad":它会冻结所有内容,直到加载所有 Elements
。
array.forEach(elements, function(element) {
element.loadConfig();
});
或
var counter = 0;
var loadConfig = function(element) {
element.loadConfig()
if (++counter <= elements.length - 1) {
loadConfig(elements(counter));
}
};
loadConfig(0);
有什么方法可以一个一个地加载和显示元素,而不是一次加载所有元素? JavaScript 没有多线程.. 所以我真的 运行 没主意了。
编辑: 尝试按照这个很好的答案 Why is setTimeout(fn, 0) sometimes useful? 中的建议使用 setTimeout()
但这并不能解决问题。看起来 Dojo 有一些东西可以防止小部件一个一个地呈现 - 它在加载所有数据时加载,然后将它们一起加载。
EDIT2:这就是 setTimeout()
被尝试使用的方式:
array.forEach(elements, function(element) {
setTimeout(function() {
element.loadConfig();
}, 0);
});
EDIT3:这是正在发生的事情的完整代码。层次结构为:TestSequence > Test > ElementsGroup > Element.
// Inside TestSequence widget:
...
var config = [someConfig1, someConfig2, ... someCondigN]
array.forEach(sequenceConfig, function(sequenceConfigItem, i) {
require(['some_path/' + sequenceConfig.type], function(cls) {
var test = new cls();
test.set('config', sequenceConfigItem);
});
}, this);
...
// Inside Test widget
...
_setConfigAttr: function(testConfig) {
elementsGroup.set('config', testConfig);
},
...
// Inside ElementsGroup widget
...
_setConfigAttr: function(elementsGroupConfig) {
array.forEach(config, function(elemenstGroupConfigItem, i) {
require(['some_path/' + elementsGroupConfigItem.type], function(cls) {
var element = new cls(); // <--- removing this solves the problem
element.set('config', elementsGroupConfigItem);
});
}, this);
},
...
// Inside Element widget
...
_setConfigAttr: function(testConfig) {
// apply simple DOM-stuff - set name, description, etc.
},
...
解决方案是将 setTimeout
与递归函数一起使用,如下所示:
var counter = 0;
recursiveFunc: function(element) {
setTimeout(function() {
// Do stuff for element[counter]
if (++counter < numberOfElements) {
recursiveFunc(element);
}
}, 0);
}
recursiveFunc(element[counter])
UI 线程仍然会有错误,但至少它没有被冻结。该解决方案被选为快速解决方案。对于长期的,决定优化代码以摆脱同步 XHR 请求。
假设我们有一个 Sequence
小部件,它加载 Element
个小部件并为每个小部件加载一些配置(通过 loadConfig()
)。示意图如下图所示:
问题是我尝试过的每一种方法都做同样的事情 "bad":它会冻结所有内容,直到加载所有 Elements
。
array.forEach(elements, function(element) {
element.loadConfig();
});
或
var counter = 0;
var loadConfig = function(element) {
element.loadConfig()
if (++counter <= elements.length - 1) {
loadConfig(elements(counter));
}
};
loadConfig(0);
有什么方法可以一个一个地加载和显示元素,而不是一次加载所有元素? JavaScript 没有多线程.. 所以我真的 运行 没主意了。
编辑: 尝试按照这个很好的答案 Why is setTimeout(fn, 0) sometimes useful? 中的建议使用 setTimeout()
但这并不能解决问题。看起来 Dojo 有一些东西可以防止小部件一个一个地呈现 - 它在加载所有数据时加载,然后将它们一起加载。
EDIT2:这就是 setTimeout()
被尝试使用的方式:
array.forEach(elements, function(element) {
setTimeout(function() {
element.loadConfig();
}, 0);
});
EDIT3:这是正在发生的事情的完整代码。层次结构为:TestSequence > Test > ElementsGroup > Element.
// Inside TestSequence widget:
...
var config = [someConfig1, someConfig2, ... someCondigN]
array.forEach(sequenceConfig, function(sequenceConfigItem, i) {
require(['some_path/' + sequenceConfig.type], function(cls) {
var test = new cls();
test.set('config', sequenceConfigItem);
});
}, this);
...
// Inside Test widget
...
_setConfigAttr: function(testConfig) {
elementsGroup.set('config', testConfig);
},
...
// Inside ElementsGroup widget
...
_setConfigAttr: function(elementsGroupConfig) {
array.forEach(config, function(elemenstGroupConfigItem, i) {
require(['some_path/' + elementsGroupConfigItem.type], function(cls) {
var element = new cls(); // <--- removing this solves the problem
element.set('config', elementsGroupConfigItem);
});
}, this);
},
...
// Inside Element widget
...
_setConfigAttr: function(testConfig) {
// apply simple DOM-stuff - set name, description, etc.
},
...
解决方案是将 setTimeout
与递归函数一起使用,如下所示:
var counter = 0;
recursiveFunc: function(element) {
setTimeout(function() {
// Do stuff for element[counter]
if (++counter < numberOfElements) {
recursiveFunc(element);
}
}, 0);
}
recursiveFunc(element[counter])
UI 线程仍然会有错误,但至少它没有被冻结。该解决方案被选为快速解决方案。对于长期的,决定优化代码以摆脱同步 XHR 请求。