it-swarm.com.de

Wie speichere ich Javascript-Funktionen in einer Warteschlange, damit sie schließlich ausgeführt werden

Ich habe eine Queue-Klasse in Javascript erstellt und möchte Funktionen als Daten in einer Queue speichern. Auf diese Weise kann ich Anforderungen (Funktionsaufrufe) aufbauen und auf diese reagieren, wenn ich sie benötige (die Funktion tatsächlich ausführen).

Gibt es eine Möglichkeit, eine Funktion als Daten zu speichern, ähnlich wie

.setTimeout("doSomething()", 1000);

außer es wäre

functionQueue.enqueue(doSomething());

Wo es doSomething () als Daten speichern würde, würde die Funktion ausgeführt, wenn ich die Daten aus der Warteschlange abrufe.

Ich vermute, ich müsste doSomething () in Anführungszeichen -> "doSomething ()" und einige, wie man die Funktion mit einem String aufruft, weiß jemand, wie das gemacht werden könnte?

70
Matt

Alle Funktionen sind eigentlich Variablen, so dass es ziemlich einfach ist, alle Ihre Funktionen in einem Array zu speichern (indem Sie sie ohne () Referenzieren):

// Create your functions, in a variety of manners...
// (The second method is preferable, but I show the first for reference.)
function fun1() { alert("Message 1"); };
var fun2 = function() { alert("Message 2"); };

// Create an array and append your functions to them
var funqueue = [];
funqueue.Push(fun1);
funqueue.Push(fun2);

// Remove and execute the first function on the queue
(funqueue.shift())();

Dies wird etwas komplexer, wenn Sie Parameter an Ihre Funktionen übergeben möchten. Sobald Sie jedoch das Framework dafür eingerichtet haben, wird es jedes Mal einfacher. Im Wesentlichen erstellen Sie eine Wrapper-Funktion, die beim Aufrufen eine vordefinierte Funktion mit einem bestimmten Kontext und Parametersatz auslöst:

// Function wrapping code.
// fn - reference to function.
// context - what you want "this" to be.
// params - array of parameters to pass to function.
var wrapFunction = function(fn, context, params) {
    return function() {
        fn.apply(context, params);
    };
}

Nachdem wir nun eine Hilfsprogrammfunktion zum Umbrechen haben, wollen wir uns ansehen, wie sie verwendet wird, um zukünftige Funktionsaufrufe zu erstellen:

// Create my function to be wrapped
var sayStuff = function(str) {
    alert(str);
}

// Wrap the function.  Make sure that the params are an array.
var fun1 = wrapFunction(sayStuff, this, ["Hello, world!"]);
var fun2 = wrapFunction(sayStuff, this, ["Goodbye, cruel world!"]);

// Create an array and append your functions to them
var funqueue = [];
funqueue.Push(fun1);
funqueue.Push(fun2);

// Remove and execute all items in the array
while (funqueue.length > 0) {
    (funqueue.shift())();   
}

Dieser Code könnte verbessert werden, indem der Wrapper entweder ein Array oder eine Reihe von Argumenten verwenden kann (dies würde jedoch das Beispiel, das ich machen möchte, durcheinander bringen).

182
Daniel Lew

Kanonische Antwort gepostet hier


Hier ist eine Nice Queue-Klasse, die Sie verwenden können , ohne Timeouts zu verwenden:

var Queue = (function(){

    function Queue() {};

    Queue.prototype.running = false;

    Queue.prototype.queue = [];

    Queue.prototype.add_function = function(callback) { 
        var _this = this;
        //add callback to the queue
        this.queue.Push(function(){
            var finished = callback();
            if(typeof finished === "undefined" || finished) {
               //  if callback returns `false`, then you have to 
               //  call `next` somewhere in the callback
               _this.next();
            }
        });

        if(!this.running) {
            // if nothing is running, then start the engines!
            this.next();
        }

        return this; // for chaining fun!
    }

    Queue.prototype.next = function(){
        this.running = false;
        //get the first element off the queue
        var shift = this.queue.shift(); 
        if(shift) { 
            this.running = true;
            shift(); 
        }
    }

    return Queue;

})();

Es kann so verwendet werden:

var queue = new Queue;
queue.add_function(function(){
   //start running something
});
queue.add_function(function(){
   //start running something 2
});
queue.add_function(function(){
   //start running something 3
});
24
Neal

Beziehen Sie sich auf die Funktion, die Sie speichern, ohne das () am Ende. doSomething ist eine Variable (das ist zufällig eine Funktion); doSomething() ist eine Anweisung zum Ausführen der Funktion.

Wenn Sie später die Warteschlange verwenden, möchten Sie etwas wie (functionQueue.pop())() - das heißt, führen Sie functionQueue.pop aus und führen Sie dann den Rückgabewert dieses Aufrufs an pop aus.

6

Sie können auch die Methode . Call () eines Funktionsobjekts verwenden.

function doSomething() {
    alert('doSomething');
}

var funcs = new Array();

funcs['doSomething'] = doSomething;

funcs['doSomething'].call();

Darüber hinaus können Sie die Funktion auch direkt zur Warteschlange hinzufügen:

funcs['somethingElse'] = function() {
    alert('somethingElse');
};

funcs['somethingElse'].call();
6
Mark Biek