How to execute a Javascript function only after multiple other functions have completed?

后端 未结 7 2025
轻奢々
轻奢々 2020-12-25 15:03

My specific problem is that I need to execute a (potentially) large number of Javascript functions to prepare something like a batch file (each function call adds some infor

7条回答
  •  自闭症患者
    2020-12-25 15:39

    If you don't use any asynchronous functions and your script doesn't break the order of execution, then the most simple solution is, as stated by Pointy and others:

    funcA(); 
    funcB();
    funcC();
    

    However, since you're using node.js, I believe you're going to use asynchronous functions and want to execute funcC after a async IO request has finished, so you have to use some kind of counting mechanisms, for example:

    var call_after_completion = function(callback){
        this._callback = callback;
        this._args = [].slice.call(arguments,1);
        this._queue = {};
        this._count = 0;
        this._run = false;
    }
    
    call_after_completion.prototype.add_condition = function(str){
        if(this._queue[str] !== undefined)
            throw new TypeError("Identifier '"+str+"' used twice");
        else if(typeof str !== "String" && str.toString === undefined)
            throw new TypeError("Identifier has to be a string or needs a toString method");
    
        this._queue[str] = 1;
        this._count++;
        return str;
    }
    
    call_after_completion.prototype.remove_condition = function(str){
        if(this._queue[str] === undefined){
            console.log("Removal of condition '"+str+"' has no effect");
            return;
        }
        else if(typeof str !== "String" && str.toString === undefined)
            throw new TypeError("Identifier has to be a string or needs a toString method");
    
        delete this._queue[str];
    
        if(--this._count === 0 && this._run === false){
            this._run = true;
            this._callback.apply(null,this._args);
        }
    }
    

    You can simplify this object by ignoring the identifier str and just increasing/decreasing this._count, however this system could be useful for debugging.

    In order to use call_after_completion you simply create a new call_after_completion with your desired function func as argument and add_conditions. func will only be called if all conditions have been removed.

    Example:

    var foo = function(){console.log("foo");}
    var bar = new call_after_completion(foo);
    var i;
    
    bar.add_condition("foo:3-Second-Timer");
    bar.add_condition("foo:additional function");
    bar.add_condition("foo:for-loop-finished");
    
    function additional_stuff(cond){
        console.log("additional things");
        cond.remove_condition("foo:additional function");
    }
    
    for(i = 0; i < 1000; ++i){
    
    }
    console.log("for loop finished");
    bar.remove_condition("foo:for-loop-finished");
    additional_stuff(bar);
    
    setTimeout(function(){
        console.log("3 second timeout");
        bar.remove_condition("foo:3-Second-Timer");
    },3000);
    

    JSFiddle Demo

提交回复
热议问题