Search code examples
node.jsgenericsasynchronouscallbackplatform

why node js donot provide a [Mother]function to call any function asynchronously with a supplied call back


Given Node.js boasts of asynchronous event driven model, I was expecting, I should be able to write any Nodejs function, e.g as simple as going through a loop, e.g IamLooper() below,
which might or might not involve file I/O and then pass that looping function to a mother nodeJs function e.g Invoke(),to which I also pass another call back functiont e.g happyend() below.

My expectation was after IamLooper is finished ,happyend () will be invoked by the NodeJs supplied function .

e.g : ==>

 gdata =[];
function IamLooper() {
var pi = Array;

for (var ii = 0 ; ii <4 ; ii ++)
{  
  pi[ii] = 13* ii;;
 gdata.push(ii);

}
console.log("looper  done -tell the callback") ;
}
function  happyend() { console.log("looper says done");}

I want to invoke IamLooper() and supply the happyend at time of invocation. i.e. I am looking for a ready made node function e.g Invoke, which can be called like this:

  Invoke(IamLooper(), happyend());
  if(gdata.length > 0) {console.log("looping has started");}

In essence Invoke should do the same for any two functions I supply to it so that we have just a working template of a callback execution strategy. Also the Invoke being executed async, my program progresses beyond Invoke before it finishes. Is my expectation is misguided ? Can any one give me some guidance here.


Solution

  • If you are looking for a preexisting way of easily doing callbacks in node, you should use event emitters (https://nodejs.org/api/events.html):

    var EventEmitter = require('events').EventEmitter;
    var eventExample = new EventEmitter;
    
    //You can create event listeners:
    eventExample.on('anEvent', function(someData){
        //Do something with someData
    });
    
    //To trigger an event listener you must emit:
    eventExample.emit('anEvent', someData);
    

    With your code, it'd look something like this:

    var EventEmitter = require('events').EventEmitter;
    var looper = new EventEmitter;
    
    looper.on('invoke', function(data){
        var callFunction = data.callFunction;
        var finishFunction = data.finishFunction;
        var callParameters = data.callParameters;
        var finishParameters = data.finishParameters;
        if(callParameters == null){
            callFunction({callbackPara: finishParameters, callbackFunction: finishFunction});
        }
        else{
            callFunction(callParameters, {callbackParameters: finishParameters, callbackFunction: finishFunction});
        }
    });
    
    looper.on('finish', function(data){
        var finishFunction = data.callbackFunction;
        var parameters = data.callbackParameters;
        if(parameters == null){
            finishFunction();
        }
        else{
            finishFunction(parameters);
        }
    });
    
    
    gdata =[];
    function IamLooper(g, callback){
        var pi = Array;
        for (var ii = 0 ; ii <4 ; ii ++){  
            pi[ii] = 13* ii;;
            g.push(ii);
        }
        looper.emit('finish', callback);
    }
    
    function  happyend() { console.log("looper says done");}
    

    And then call it like:

    looper.emit('invoke', {callFunction: IamLooper, finishFunction: happyend, callParameters: gdata, finishParameters: null});
    

    You can also always do normal callbacks:

    gdata =[];
    function IamLooper(g, callback){
        var pi = Array;
        for (var ii = 0 ; ii <4 ; ii ++){  
            pi[ii] = 13* ii;;
            g.push(ii);
        }
        callback();
    }
    IamLooper(gdata, function(){ console.log("looper says done");}