1

Hi all I have this working method to call an array of functions at recurring intervals.

Here you can see the object with the methods to add/remove functions in the array and the functions to start/stop the calling interval. (You have to focus only to the start method but I put them all for clarification)

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 = [];
    }
}

I want to convert the start method using setTimeout instead of setInterval and I wrote something like this:

updateEngine.prototype.start = function () {
    function doLoop() {
        $.when.apply($, _functionsToCall)
            .done(function() {
                setTimeout(doLoop, _updateFrequence);
            });
    }

    setTimeout(doLoop, _updateFrequence);
}

How can I change the context of the array functions _functionsToCall like I do in the previous method to pass the iframe context to each function?

Adam Michalik
  • 9,678
  • 13
  • 71
  • 102
Mat
  • 11
  • 3
  • seems that what you are wanting is to only loop over `arguments` of `$.when.done` – charlietfl Feb 26 '15 at 15:16
  • I have to iterate through each function to change the context... so how can I do this inside $.when statement? – Mat Feb 26 '15 at 15:33
  • I want to better explain the environment of my application. I have a containing page with the js function I've poseted above and inside this page I will load/unload some iframes.. In each iframe I can add/remove an iframe function to "_callRecurringFunctions" array so all the functions in this array can be executed with a certain frequence. The main problem is to set the execution context of each function to the correct iframe that added it to the array – Mat Feb 27 '15 at 10:59
  • so why can't you use `arguments.length` and run similar loop as exists already? – charlietfl Feb 27 '15 at 11:32
  • mhh.. maybe you are talking about something I don't know.. can you provide an example please? I'm looking for $.proxy right now and I think it should be a possible solution – Mat Feb 27 '15 at 11:35
  • looking again I don't see any use of promises that would make `$.when` useful anyway. Is a bit confusing what you are doing in general since I don't know the rest of the app – charlietfl Feb 27 '15 at 11:43
  • _callRecurringFunctions is an array of deferred promises – Mat Feb 27 '15 at 11:50
  • can't you resolve them with the context needed? The array of resolves will be `arguments` in `$.when.done` – charlietfl Feb 27 '15 at 11:54

1 Answers1

0

I've resolved my problem in another way... Now I have an array of functions that return a promise each; Those functions can be declared inside differents iframes; I increase a counter when each promise is resolved, and when all promises are resolved I can start again with another loop. Obviously on each iteration the array can contains a different number of functions.

I'd like to know if there is a better way to do this task or if there are some issues with my code. Thank you all.

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)
    }
Mat
  • 11
  • 3