Chapter 36 Tag-Based Development with CSP - Use as few #server and #call calls as possible

Chapter 36 Tag-Based Development with CSP - Use as few #server and #call calls as possible

#server and #call work by having the browser make an HTTP request to the page containing a special encrypted token that tells Caché the name of the method to run.
Caché runs this method, any output it sends back is executed as JavaScript on the browser, and the #server call can also return a value.
Because these calls all use HTTP requests, they have roughly the same overhead in terms of network packets, CPU on the server, etc. as normal CSP page requests.
If a large number of #server requests are used, then it will greatly reduce the scalability of the application, as each #server call requires a new CSP page from the Caché server.
This means that, unlike traditional web pages (i.e. you visit the URL and generate the page once), a CSP page with 10 server calls costs the same as generating 10 CSP pages;
If you can reduce the number of #server calls, you can increase the number of users your application supports by a factor of 10.

The way to reduce the number of #server calls is to make sure that every #server call used is what the application really needs, and if so, make sure that this #server call does as much work as possible on the server.
For example, below is a JavaScript block that updates a form with some new values ​​from the server.

Note that this code uses the CSP keyword CSPPage to refer to the page itself, not the Javascript keyword self.
In this example, the two keywords do the same thing.
We recommend using CSPPage because self can act unexpectedly in different contexts.

<script language="JavaScript">
function UpdateForm()
{
   CSPPage.document.form.Name.value = #server(..workGet("Name",objid))#;
   CSPPage.document.form.Address.value = #server(..workGet("Address",objid))#;
   CSPPage.document.form.DOB.value = #server(..workGet("DOB",objid))#;
}
</script>

The server code is shown below.
(Usually it would use an object or SQL, but here we use a global to keep the code small.)

<script language="Cache" method="workGet"
 arguments="type:%String,id:%String" returntype="%String">
   Quit $get(^work(id,type))
</script>

This update makes three new page calls from the Caché servers!
This can be translated into a #server call to update all values ​​at once, the JavaScript becomes:

<script language="JavaScript">
function UpdateForm()
{
   #server(..workGet(objid))#;
}
</script>

The method is defined as:

<script language="Cache" method="workGet"
 arguments="id:%String" returntype="%String">
   &js<CSPPage.document.form.Name.value = #($get(^work("Name",objid)))#;
      CSPPage.document.form.Address.value = #($get(^work("Address",objid)))#;
      CSPPage.document.form.DOB.value = #($get(^work("DOB",objid)))#;>
</script>

So instead of calling it multiple times, just pass the data once and let Caché do all the work.
If you have a more complex JavaScript example like:

<script language="JavaScript">
function UpdateForm()
{
   CSPPage.document.form.Name.value = #server(..workGet("Name",objid))#;
   if (condition) {
      CSPPage.document.form.DOB.value = #server(..workGet("DOB",objid))#;
   }
   else {
       CSPPage.document.form.DOB.value = '';
   }
}
</script>

Then this should still only require one #server call.
You just need to embed the entire if condition into the JavaScript returned by the #server call, so the code for the workGet method ends up looking like this:

<script language="Cache" method="workGet"
 arguments="id:%String" returntype="%String">
   &js<CSPPage.document.form.Name.value = #(^work("Name",objid))#;
      if (condition) {
         CSPPage.document.form.DOB.value = #(^work("DOB",objid))#;
      }
      else {
         CSPPage.document.form.DOB.value = '';
      }
   >
</script>

Create custom HyperEvent error handlers for #server and #call

If you use a super event (#server or #call) to call something, and when it executes, it fails to communicate with the server for some reason, and then generates an error, then the default behavior of CSP is to display the error in an alert box .
If you want to handle the error separately, such as logging it or displaying a different message to the user, write a cspRunServerMethodError JavaScript function.
The following example displays errors in an alert box like the default behavior:

function cspRunServerMethodError(errortext,error)
{
   //alert('cspRunServerMethodError - cspHyperEventErrorHandler\n\nerrortext:' + errortext + '\n\nerror-object:\n' + JSON.stringify(error, null, 4) );
    
   if (error.code == '401') {
      document.location.href = '#(..Link(%request.URL))#'; //reloads the page
   }
   else {
      //...
   }

   return null;
  
}

The cspHyperEventError object type has the following properties and values:

  • code: Corresponds to the HTTP response code or the response code from the XMLHttpRequest object being used.
    XMLHttpRequest code may be browser specific.
  • text: A free text field corresponding to the current text returned to the cspRunServerMethodError() callback function.
  • serverCode: Corresponds to the error number on the server (if available).
    This value can be empty.
  • serverText: The error message from the server, if available.
    The value defaults to the empty string, which is " ".
  • exception: The exception that triggered the error.
    This value can be empty.
  • arguments: The list of arguments to the function that caught the exception.
    This value can be empty and is only populated if an exception is defined.

Posted by sirfartalot on Fri, 04 Nov 2022 04:22:05 +0300