Как хранить функции javascript в очереди для их выполнения в конечном итоге

Я создал класс Queue в javascript, и я хотел бы хранить функции в виде данных в очереди. Таким образом, я могу создавать запросы (вызовы функций) и отвечать на них, когда мне нужно (фактически выполнять функцию).

Есть ли способ сохранить функцию как данные, несколько похожую на

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

кроме

functionQueue.enqueue(doSomething());

Где он будет хранить doSomething() в качестве данных, поэтому, когда я получаю данные из очереди, функция будет выполнена.

Я предполагаю, что мне пришлось бы делать doSomething() в кавычках → "doSomething()", а некоторые - как заставить его вызывать функцию с помощью строки, кто-нибудь знает, как это можно сделать?

Ответ 1

Все функции фактически являются переменными, поэтому на самом деле довольно легко хранить все ваши функции в массиве (путем ссылки на них без ()):

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

Это становится немного более сложным, если вы хотите передать параметры своим функциям, но как только вы настроите фреймворк для этого, как только это станет легче каждый раз после этого. По существу, вы должны создать функцию-оболочку, которая при вызове запускает предопределенную функцию с определенным контекстом и набором параметров:

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

Теперь, когда у нас есть функция утилиты для переноса, давайте посмотрим, как она использовалась для создания будущих вызовов функций:

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

Этот код можно было бы улучшить, разрешив оболочке либо использовать массив, либо ряд аргументов (но это будет путать пример, который я пытаюсь сделать).

Ответ 2

Канонический ответ отправлен здесь


Вот хороший класс Queue, который вы можете использовать без для использования тайм-аутов:

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;

})();

Его можно использовать так:

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

Ответ 3

Обратитесь к функции, которую вы храните без() в конце. doSomething - переменная (которая является функцией); doSomething() - это инструкция для выполнения функции.

Позже, когда вы используете очередь, вам нужно что-то вроде (functionQueue.pop())() - то есть выполнить функцию functionQueue.pop, а затем выполнить возвращаемое значение этого вызова для pop.

Ответ 4

Вы также можете использовать метод .call() объекта функции.

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

var funcs = new Array();

funcs['doSomething'] = doSomething;

funcs['doSomething'].call();

Кроме того, вы также можете добавить функцию непосредственно в очередь:

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

funcs['somethingElse'].call();