如何将 javascript 函数存储在队列中以便最终执行

IT技术 javascript function timeout queue
2021-03-06 16:11:22

我在 javascript 中创建了一个 Queue 类,我想将函数作为数据存储在队列中。这样我就可以建立请求(函数调用)并在需要时响应它们(实际上是执行函数)。

有没有办法将函数存储为数据,有点类似于

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

除了它会

functionQueue.enqueue(doSomething());

它将 doSomething() 作为数据存储在哪里,所以当我从队列中检索数据时,该函数将被执行。

我猜我必须在引号中使用 doSomething() -> "doSomething()" 以及一些如何使用字符串调用函数的方法,有人知道怎么做吗?

4个回答

所有函数实际上都是变量,因此实际上很容易将所有函数存储在数组中(通过在没有 的情况下引用它们()):

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

可以通过允许包装器使用数组或一系列参数来改进此代码(但这样做会混淆我正在尝试制作的示例)。

我自己已经这样做了很多,但从未想过同时存储上下文和参数。非常好。
2021-04-26 16:11:22
如果您想捕获内部函数的返回结果,请使用以下命令: return fn.apply(context, params);
2021-04-29 16:11:22
谢谢,一旦它们滚动到视口上方,我就很难顺利删除页面顶部的元素。iOS 8 使这变得困难,您的速度检测挽救了这一天!
2021-05-05 16:11:22
它如何处理像ajax请求这样的宽度异步方法,我如何链接ajax方法?
2021-05-08 16:11:22
函数不是变量,它们是对象。不过非常有帮助的帖子!谢谢!
2021-05-17 16:11:22

此处发布的规范答案


这是一个不错的 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
});
在许多情况下,不使用 setTimeout 就可以了。拥有 setTimeout 当然(在这里提到这一点)有助于将执行返回给 Javascript task queue/ event loop通过这个冗长的代码部分不会阻塞浏览器。
2021-05-10 16:11:22

在末尾没有 () 时,请参阅您要存储的函数。 doSomething是一个变量(恰好是一个函数);doSomething()是执行函数的指令。

稍后,当您使用队列时,您将需要类似的东西(functionQueue.pop())()——也就是说,执行 functionQueue.pop,然后执行对 pop 的调用的返回值。

您还可以使用函数对象.call()方法。

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

var funcs = new Array();

funcs['doSomething'] = doSomething;

funcs['doSomething'].call();

另外,也可以直接将函数添加到队列中:

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

funcs['somethingElse'].call();