How to link a JavaScript file to make asynchronous requests from Sage X3

 In Development, Sage X3

In this blog post, we will see how to make requests from Sage to a JavaScript file in an asynchronous way as well as some advice to make our lives easier.

Do you want to implement Sage in your company?


Let’s start with the basics, create a new folder and create the following file structure


It’ s in this image when we can already appreciate the first trick for our developments, and it’ s that, to make some changes in our scripts, if we only have the index, we would have to restart Syracuse for these changes to be effective. However, if in our index, we link a separate js (in our case, eaxexample-service._js) and we call it from the requireUncache function, our js will not be cached and we will be able to update it


function requireUncached(module) {

    delete require.cache[require.resolve(module)]

    return require(module)



Another point to mention, is that the extension used (_js) is to indicate to Sage that an asynchronous function is going to be performed, using the streamline.js package with the callback _. More information in the corresponding Sage guide.

Once the file structure is done, we will write our package.json, in which we will declare our author, name of the script, version and description of it and the module(s) to be loaded


Finally, before starting to develop the call to the api, we will configure the index to call our service. To do this, within the js we create the function exports.query as follows:

exports.query = function(_, params) {

    let res;

    const EAXExampleService = requireUncached("./services/eaxexample-service");

    const eaxexample = new EAXExampleService();

    try {

        res = eaxexample.query(_, params);

        // Result of http response

    } catch (error) {

        //If any error happens, it's written inside a log

        fs.appendFileSync("C:/logpath/eax_log.txt", "\n-----------------------------------------------\n[" + new Date().toLocaleString() + "] SUBMIT => Error Data: " + error);


    return res



As we can see, inside the function, first we create a service calling the script with our requireUncached function to make sure that is loaded with the last changes made, then the query is executed passing through parameters the _ and the parameters that arrive through Sage, finally, if there has not been any error (in that case a log would be written in the specified path), it returns the response from the api.

Within our service (eaxexample-service._js) we export the EAXExampleService class.

In our class constructor we will find the url and path of the api to which we will make the request


Then, we create a small function to pass the arguments received from Sage to a string in order to pass it by parameter to the URL


And finally, we created our query function, which is the one that will make the call

query = (_, args) => {

        let response = '';

        let params, res;

        try {

            params = this.objectToQueryParams(args);

            // Declaring request options

            var options = {

                'method': 'GET',

                'url': this.HOSTNAME+this.BASE_PATH+params,

                'headers': this.BASE_HEADERS,


            // Setting up the request

            response = httpClient.httpRequest(_, options).end().response(_);

            res = response.readAll(_);

            res = JSON.parse(res);

            return res;

        } catch (error) {

            //If any error happens, it's written inside a log

            fs.appendFileSync("C:/logPath/eax_log.txt", "QUERY REQUEST ERROR - [" + new Date().toLocaleString() + "] " + error + "\n");

            res = { 'error': 'Error fetching query' };


        return res;




As we can see, we use the httpClient library to make a request along with the previously configured options by passing our callback “_”, then we read its response and parse our response to an object.

Again, if an error occurs somewhere in our query, we capture it and write it in our log.

Finally, in case we want only some data, we can create a function that filters our response before returning it.

If everything went well, our answer will be sent back to Sage.

Once the json and the index are written, we open the path to the Node modules of our Syracuse (usually located in C:\Sage\SafeX3\SyracuseComponent\binode_modules) and copy the newly created folder


Then, we restart the Syracuse service and, once started, we will have our script ready and, if we want to modify it, we will not have to restart the service again.

Finally, inside the Sage script, to call the JavaScript file, we declare the arguments that we will pass to the EXEC_JS function

### Module, function and element to be returned

Local Char MODULE(100) : MODULE = "zeaxexample/lib/index" # Script location

Local Char FONCTION(30) : FONCTION = "query" #'getUserProfile'

Local Char RETURNS(50) : RETURNS = ""

### The function is asynchronous

Local Char MODE(4) : MODE = "wait"

### The callback argument is located in the first place for this function

Local Integer CALLB : CALLB = -1

### No Base 64 in or out coding, the arguments can remain empty

Local Char B64_IN(20): B64_IN = "0"

Local Char B64_OUT(20): B64_OUT = "0"

### No additional arguments


# Let's call the function



This function takes as parameters the file you need (._js), the name of the function, if you need to filter the answer, if the function is asynchronous, if the answer is coded and the parameters of it

When that function is finished, the api response will be stored in the variable RESBODY

I hope it was useful!

Do you have an SME? We help you!

At Emiral we know how much your company is worth, whether it is small or medium sized. That is why we want to offer you the best solutions to keep your business growing.

José Elías Enrique

Desarrollador web en EMIRAL

Recommended Posts

Leave a Comment