Using JSDOs to create mobile and web clients : Accessing custom Invoke operations : Invoke operation example : Client JavaScript code: An Invoke
  
Client JavaScript code: An Invoke
The following JavaScript illustrates an asynchronous call to the preceding method using an afterInvoke event callback (onAfterInvokeGetCreditInfo) to handle the results:
dsCustomer.subscribe('afterInvoke', 'GetCreditInfo',
                        onAfterInvokeGetCreditInfo);
var currentCust = { piCustNum : 10 };

dsCustomer.GetCreditInfo ( currentCust );

function onAfterInvokeGetCreditInfo (jsdo , success , request ) {
    /* check for errors on this Invoke operation */
    if (success) {
        /* do the normal thing for a successful Invoke operation. */
        /* for example, evaluate the CreditLimit for Customer currentCust
           and if their Balance is greater, display a message . . . */
        if (request.response._retVal && request.response._retVal < 1000.00) {
            var poCustomer = request.response.poCustomer.poCustomer;
            if (dsCustomer.find(function(jsrecord) {
                    return (jsrecord.data.CustNum == poCustomer[0].data.CustNum);
                }) {
                if (dsCustomer.Balance > request.response._retVal) {
                    console.log("Customer "
                        + dsCustomer.CustNum + " " + dsCustomer.Name
                        + " has a Balance higher than their CreditLimit"
                    );
                }
            }
        }
    }
    else {
        /* return errors from this Invoke operation */
        if (request.response && request.response._errors &&
            request.response._errors.length > 0){

            var lenErrors = request.response._errors.length;
            for (var idxError=0; idxError < lenErrors; idxError++) {
                var errorEntry = request.response._errors[idxError];
                var errorMsg = errorEntry._errorMsg;
                var errorNum = errorEntry._errorNum;
                /* handle Invoke operation error . . . */

            }
        }
    }
};
This sample code:
*Subscribes an event-handler callback, onAfterInvokeGetCreditInfo, to the afterInvoke event to enable error-checking and processing of the results.
*Defines the object variable, currentCust, to specify the value of the piCustNum input parameter passed to GetCreditInfo( ).
*Calls GetCreditInfo( ) on the dsCustomer JSDO asynchronously.
*The callback function tests for the success of the Invoke operation and accesses both the operation return value (_retVal) and its one output parameter (poCustomer) to do the normal thing for a successful execution, and accesses any returned errors for an unsuccessful execution.
*In the assignment of request.poCustomer.poCustomer to the poCustomer variable, the parameter name (poCustomer) must be specified twice. The first instance refers to the parameter name as defined in the ABL routine; the second instance is the name of the JavaScript object containing the table data that the server serializes as JSON to send to the client.
The following JavaScript illustrates an asynchronous call to the same method using Promise callbacks to handle the results:
var currentCust = { piCustNum : 10 };

dsCustomer.invoke ( "GetCreditInfo", currentCust ).done(
function( jsdo, success, request ) {
        /* do the normal thing for a successful Invoke operation. */
        /* for example, evaluate the CreditLimit for Customer currentCust
           and if their Balance is greater, display a message . . . */
        if (request.response._retVal && request.response._retVal < 1000.00) {
            var poCustomer = request.response.poCustomer.poCustomer;
            if (dsCustomer.find(function(jsrecord) {
                    return (jsrecord.data.CustNum == poCustomer[0].data.CustNum);
                }) {
                if (dsCustomer.Balance > request.response._retVal) {
                    console.log("Customer "
                        + dsCustomer.CustNum + " " + dsCustomer.Name
                        + " has a Balance higher than their CreditLimit"
                    );
                }
            }
        }
}).fail(
function( jsdo, success, request ) {
        /* return errors from this Invoke operation */
        if (request.response && request.response._errors &&
            request.response._errors.length > 0) {

            var lenErrors = request.response._errors.length;
            for (var idxError=0; idxError < lenErrors; idxError++) {

                var errorEntry = request.response._errors[idxError];
                var errorMsg = errorEntry._errorMsg;
                var errorNum = errorEntry._errorNum;
                /* handle Invoke operation error . . . */

            }
        }
});
This sample code:
*Defines the object variable, currentCust, to specify the value of the piCustNum input parameter passed to GetCreditInfo( ).
*Calls GetCreditInfo( ) on the dsCustomer JSDO asynchronously using the JSDO invoke( ) API to return a Promise object.
*Chains access to the done( ) method on the returned Promise object to register a callback function that handles successful operation execution. This callback accesses both the Invoke operation return value (_retVal) and its one output parameter (poCustomer) to do the normal thing for a successful execution.
*Chains access to the fail( ) method on the returned Promise object to register a callback function that handles unsuccessful operation execution. This callback accesses and handles any returned errors.
*In the assignment of request.poCustomer.poCustomer to the poCustomer variable, the parameter name (poCustomer) must be specified twice. The first instance refers to the parameter name as defined in the ABL routine; the second instance is the name of the JavaScript object containing the table data that the server serializes as JSON to send to the client.
The following JavaScript illustrates a synchronous call to the same method:
var currentCust = { piCustNum : 10 };
var request = null;

try {
    request = dsCustomer.GetCreditInfo ( currentCust, false ));
    if (!request.success) {
        throw "Invoke request to GetCreditInfo() not successful for CustNum == "
            + "for CustNum == " + currentCust.piCustNum.toString();
    }
    /* do the normal thing for a successful Invoke operation. */
    /* for example, evaluate the CreditLimit for Customer currentCust
       and if their Balance is greater, display a message . . . */
    else if (request.response._retVal && request.response._retVal < 1000.00) {
        var poCustomer = request.response.poCustomer.poCustomer;
        if (dsCustomer.find(function(jsrecord) {
                return (jsrecord.data.CustNum == poCustomer[0].data.CustNum);
            }) {
            if (dsCustomer.Balance > request.response._retVal) {
                console.log("Customer "
                    + dsCustomer.CustNum + " " + dsCustomer.Name
                    + " has a Balance higher than their CreditLimit"
                );
            }
        }
        else {
            /* No such record in dsCustomer */
            throw "No dsCustomer record with CustNum == "
                + currentCust.piCustNum.toString();
        }
    }
    else {
        throw "dsCustomer.GetCreditInfo() returns "
            + "out-of-range CreditLimit for CustNum == "
            + currentCust.piCustNum.toString();
    }
}
catch(err) {
    /* handle error with access to request . . . */
};
This sample code:
*Defines two object variables: currentCust to specify the value of the piCustNum input parameter passed to GetCreditInfo( ), and request to hold the request object reference returned as the value of GetCreditInfo( ).
*Uses try...catch blocks to handle certain errors.
*Calls GetCreditInfo( ) on the dsCustomer JSDO to test the contents of its returned request object, and either do the normal thing for a successful execution or throw various error strings for an unsuccessful Invoke operation or other errors encountered.
*Might not be a good example of an Invoke operation for synchronous execution, because it is not executed to return a value within an expression, and in addition to a return value it also returns an output parameter (poCustomer) containing the corresponding Customer record with a small subset of fields. Searching a large result set for the specified record to return in this output parameter can block for an extended period of time.