Question Comment puis-je stocker les fonctions javascript dans une file d'attente pour les exécuter éventuellement [dupliquer]


Cette question a déjà une réponse ici:

J'ai créé une classe Queue en javascript et je voudrais stocker les fonctions en tant que données dans une file d'attente. De cette façon, je peux créer des requêtes (appels de fonction) et y répondre lorsque j'en ai besoin (exécuter la fonction).

Existe-t-il un moyen de stocker une fonction sous forme de données, quelque peu similaire à

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

sauf que ce serait

functionQueue.enqueue(doSomething());

Où il stockerait doSomething () en tant que données alors quand je récupérerais les données de la file d'attente, la fonction serait exécutée.

Je suppose que je devrais avoir doSomething () entre guillemets -> "doSomething ()" et d'autres comment faire appel à la fonction en utilisant une chaîne, tout le monde sait comment cela pourrait être fait?


65
2018-05-22 17:51


origine


Réponses:


Toutes les fonctions sont en fait des variables, il est donc assez facile de stocker toutes vos fonctions dans un tableau (en les référençant sans ()):

// 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())();

Cela devient un peu plus complexe si vous voulez passer des paramètres à vos fonctions, mais une fois que vous avez configuré le cadre pour le faire une fois qu'il devient facile à chaque fois. Essentiellement, vous allez créer une fonction wrapper qui, lorsqu'elle est appelée, déclenche une fonction prédéfinie avec un contexte et un jeu de paramètres particuliers:

// 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);
    };
}

Maintenant que nous avons une fonction d'utilitaire pour l'emballage, voyons comment elle est utilisée pour créer de futurs appels de fonctions:

// 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())();   
}

Ce code pourrait être amélioré en autorisant le wrapper à utiliser un tableau ou une série d'arguments (mais cela compliquerait l'exemple que j'essaie de faire).


173
2018-05-22 17:56



Réponse canonique affichée ici


Voici une classe de file d'attente intéressante que vous pouvez utiliser sans pour autant l'utilisation de délais d'attente:

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;

})();

Il peut être utilisé comme ça:

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
});

22
2017-07-08 15:03



Reportez-vous à la fonction que vous stockez sans le () à la fin. doSomething est une variable (qui se trouve être une fonction); doSomething() est une instruction pour exécuter la fonction.

Plus tard, lorsque vous utiliserez la file d'attente, vous voudrez quelque chose comme (functionQueue.pop())() - c'est-à-dire exécuter functionQueue.pop, puis exécuter la valeur de retour de cet appel à la pop.


6
2018-05-22 17:55



Vous pouvez également utiliser le .appel() méthode d'un objet fonction.

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

var funcs = new Array();

funcs['doSomething'] = doSomething;

funcs['doSomething'].call();

De plus, vous pouvez également ajouter la fonction directement à la file d'attente:

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

funcs['somethingElse'].call();

6
2018-05-22 17:56