web-dev-qa-db-ja.com

JavaScript関数を最終的に実行されるようにキューに格納するにはどうすればよいですか

JavaScriptでQueueクラスを作成しました。関数をデータとしてキューに保存したいと思います。そうすれば、要求(関数呼び出し)を作成し、必要なときに(実際に関数を実行して)応答できます。

関数をデータとして保存する方法はありますか?

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

それを除いて

functionQueue.enqueue(doSomething());

DoSomething()をデータとして保存するため、キューからデータを取得すると、関数が実行されます。

私はdoSomething()を引用符で囲む必要があると推測しています-> "doSomething()"と文字列を使用して関数を呼び出す方法がありますが、誰もそれを行う方法を知っていますか?

70
Matt

すべての関数は実際には変数であるため、実際にすべての関数を配列に格納するのは非常に簡単です(()なしで参照することにより)。

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

このコードは、ラッパーが配列または一連の引数のいずれかを使用できるようにすることで改善できます(ただし、そうすると、作成しようとしているサンプルが混乱します)。

182
Daniel Lew

正規回答が投稿されました こちら


タイムアウトを使用せずになしで使用できるNice 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
});
24
Neal

最後に()を付けずに保存する関数を参照してください。 doSomethingは変数です(たまたま関数です)。 doSomething()は、関数を実行するための命令です。

後で、キューを使用しているときに、(functionQueue.pop())()-つまり、functionQueue.popを実行してから、popの呼び出しの戻り値を実行します。

6

関数オブジェクトの。call()メソッドを使用することもできます。

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

var funcs = new Array();

funcs['doSomething'] = doSomething;

funcs['doSomething'].call();

さらに、キューに関数を直接追加することもできます。

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

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