Измените контекст функций массива и передайте массив в $.when
Привет всем, у меня есть этот рабочий метод для вызова массива функций через повторяющиеся интервалы.
Здесь вы можете увидеть объект с методами добавления / удаления функций в массиве и функциями для запуска / остановки интервала вызова. (Вы должны сосредоточиться только на метод начала, но я поставил их все для пояснения)
function updateEngine() {
var _callRecurringFunctions = null,
_functionsToCall = [],
_functionIds = [],
_functionApps = [];
updateEngine.prototype.addFunction = function (appCode, funcId, func) {
if ($.isFunction(func) &&
$.inArray('_' + appCode + '_' + funcId, _functionIds) == -1) {
_functionApps.push(appCode);
_functionIds.push('_' + appCode + '_' + funcId);
_functionsToCall.push(func);
}
}
updateEngine.prototype.removeFunction = function (appCode, funcId) {
if (funcId == null) { // remove all functions relative to an app
for (var x = 0; x < _functionApps.length; x++) {
if (_functionApps[x] == appCode) {
_functionApps.splice(x, 1);
_functionIds.splice(x, 1);
_functionsToCall.splice(x, 1);
}
}
}
else { // remove the single app function
var pos = $.inArray('_' + appCode + '_' + funcId, _functionIds);
if (pos >= 0) {
_functionApps.splice(pos, 1);
_functionIds.splice(pos, 1);
_functionsToCall.splice(pos, 1);
}
}
}
updateEngine.prototype.start = function () {
_callRecurringFunctions = setInterval(function () {
for (var x = 0; x < _functionsToCall.length; x++) {
var frame = null;
// id == -1: local function
// id == 0: function defined in home iframe
// id > 0: function defined in an app iframe
if (_functionApps[x] >= 0)
frame = _portalContent.find("iframe[id='" + _functionApps[x] + "']");
if (frame != null && frame.get(0) != null) {
var iframeContent = frame.get(0).contentWindow || frame.get(0).contentDocument;
_functionsToCall[x].apply(iframeContent);
}
else
_functionsToCall[x]();
}
}, _updateFrequence); // tick every 5 seconds
}
updateEngine.prototype.stop = function () {
clearInterval(_callRecurringFunctions);
_callRecurringFunctions = null;
_functionApps = [];
_functionIds = [];
_functionsToCall = [];
}
}
Я хочу преобразовать start
метод с использованием setTimeout
вместо setInterval
и я написал что-то вроде этого:
updateEngine.prototype.start = function () {
function doLoop() {
$.when.apply($, _functionsToCall)
.done(function() {
setTimeout(doLoop, _updateFrequence);
});
}
setTimeout(doLoop, _updateFrequence);
}
Как я могу изменить контекст функций массива _functionsToCall
как я делал в предыдущем методе, чтобы передать контекст iframe для каждой функции?
1 ответ
Я решил свою проблему по-другому... Теперь у меня есть массив функций, которые возвращают обещание каждая; Эти функции могут быть объявлены внутри различных iframes; Я увеличиваю счетчик, когда каждое обещание разрешено, и когда все обещания разрешены, я могу начать снова с другого цикла. Очевидно, что на каждой итерации массив может содержать разное количество функций.
Я хотел бы знать, есть ли лучший способ выполнить эту задачу или есть какие-то проблемы с моим кодом. Спасибо вам всем.
updateEngine.prototype.start = function () {
function doLoop() {
var count = 0,
functionsCount = _functionsToCall.length
for (var x = 0; x < functionsCount; x++) {
var frame = null;
// id == -1: local function
// id >= 0: function defined in iframe
if (_functionApps[x] >= 0)
frame = _portalContent.find("iframe[id='" + _functionApps[0] + "']");
if (frame != null && frame.get(0) != null) {
var iframeContent = frame.get(0).contentWindow || frame.get(0).contentDocument;
$.when.apply(iframeContent, _functionsToCall[x]())
.done(function () {
count++;
})
.fail(function () {
count++;
console.log("err")
})
.always(function () {
if (count == functionsCount)
setTimeout(doLoop, _updateFrequence)
})
}
else
$.when(_functionsToCall[x]())
.done(function () {
count++;
})
.fail(function () {
count++;
console.log("err")
})
.always(function () {
if (count == functionsCount)
setTimeout(doLoop, _updateFrequence)
})
}
}
setTimeout(doLoop, _updateFrequence)
}