Can I create a script include which is singleton ? I want this to be initialized only once ?

rajeevnadgauda
ServiceNow Employee
ServiceNow Employee

This is what I have written in the script include 

The problem is I need the same ServerPubSub instance every time I refer it either in the Business Rule or other script includes. Is that possible currently it is initializing the whole script again when I use it at two places.

 

var ServerPubSub = function () {
    this.events = {};

    this.on = function (eventName, fn) {
        var self = this;



        self.events[eventName] = self.events[eventName] || [];
        gs.log(JSON.stringify(self.events) + " ---> ON REGISTERED 1" + fn);
        self.events[eventName].push(fn);
        gs.log(JSON.stringify(self.events) + " ---> ON REGISTERED");
    }
    this.off = function (eventName, fn) {
        var self = this;
        if (self.events[eventName]) {
            for (var i = 0; i < self.events[eventName].length; i++) {
                if (self.events[eventName][i] === fn) {
                    self.events[eventName].splice(i, 1);
                    break;
                }
            }
        }
    }
    this.emit = function (eventName, data) {
        var self = this;
        gs.log("Emitting ..... " + eventName + " -----> " + JSON.stringify(data));
        var self = this;
        if (self.events[eventName]) {
            self.events[eventName].forEach(function (fn) {
                fn(data);
            });
        }
        gs.log(JSON.stringify(self.events) + " ---> ON EMIT");
    }
}
ServerPubSub.prototype = {
    initialize: function () {
    },
    type: 'ServerPubSub'
};

ServerPubSub.instance = new ServerPubSub();
8 REPLIES 8

SanjivMeher
Kilo Patron
Kilo Patron

Are you not able to call this script from other script includes or BR?

 


Please mark this response as correct or helpful if it assisted you with your question.

I am able to call it but the state data of ServerPubSub.instance is not same.

 

So lets say I do something like this in some other Script include 

 

// other script which uses ServerPubSub to subscribe to event


ServerPubSub.instance.on('event.name', function() { 

//handler
})


In the BR i have this code 

ServerPubSub.instance.emit('event.name', {data : current.something})

I expect both references ServerPub.instance to point to the same instance as I am not re instantiating that script include.

So that a registered event can be handled.

 

Javier Arroyo
Kilo Guru

Singleton 1

var Singleton1 = {
   something: function () {

   },

   something2: function () {

  }
}



//call it as 

Singleton1.something();

 

Singleton 2

var Singleton2 = (function () {
   
    function doSomething1 () {

    }

    function doSomething2 () {


    }

    var publicAPI = {
        something1: doSomething1,
        something2: doSomething2
    }
})();

//call it as
Singleton2.something2;

 

Functional

function ServerPubSub(param) {

   //initialize here

   return function doSomethingElse(param2) {
      //do something here
   }

}

//use it as such.

var serverPub = ServerPubSub(argument);
serverPub(argument2);


 

 

If you need more help, elaborate a bit further. Especially in how you plan to use it. This might lead to bootstrapping the business rules.

In my opinion there are very few reasons to use the Creation pattern as SNow currently does with script includes. 

 

The SN Nerd
Giga Sage
Giga Sage

It is possible to create a Singleton Script Include.

My Use Case was to pre-populate variables in a Catalogue Item based on fields from a New Call.

I did this using a Singleton Script Include to get the New Call record and call it in the Default Value for each variable.

I have provided an example below that shows how to create a Singleton with a getValue method for a single GlideRecord.

var SingletonScriptInclude = (function () {
	
	/*
    ** Instance Variables
    */
	
    var grSingleInstance;
       
    return {
        
        /*
        ** Public functions
        */
        
        getValue: function (label) {
            var fieldValue = '';
       
            if (gs.nil(grSingleInstance)) {
                grSingleInstance = getGR();
            }

            if (!gs.nil(grSingleInstance) && grSingleInstance.isValid() ) {
                fieldValue = grSingleInstance.getValue(label);
                if (gs.nil(fieldValue)) {
                    fieldValue = '';
                } 
            }

            return fieldValue;
        }
    };
    
    /*
    ** Private functions
    */
    
    function getGR() {
        var gr = new GlideRecord('task');  
        gr.addQuery('active',true);
        gr.setLimit(1);
        gr.query(); 
		if (!gr.next()) {
            throw("Could not find GR");
        }
        return gr;
    }

})();

The code below shows how it works:

gs.addInfoMessage(SingletonScriptInclude.getValue('number'));
gs.addInfoMessage(SingletonScriptInclude.getValue('short_description'));
gs.addInfoMessage(SingletonScriptInclude.getValue('number'));

Output:

Querying for GR
TASK0020001
GR already loaded into singleton
See the audit results below for the discrepancies that must be addressed
GR already loaded into singleton
TASK0020001

ServiceNow Nerd
ServiceNow Developer MVP 2020-2022
ServiceNow Community MVP 2019-2022