Switch statements in Server-Side Javascript

Posted by cohezive on 24-Oct-2013 11:36

I'm having an issue with a simple Switch statement in a Trigger.    In my specific case, I have parsed a REST XML response from an Integration Link and need to evaluate the result and appropriate actions.

var nodeName = node.nodeName;
switch(nodeName) {
  case 'MessageType1':
    //  do something
    break;
  case 'MessageType2':
    // do something else
    break;
  default:
      // Invalid or Unsupported Node Name
}

All values pass through to the default.  When I replace the switch statement with If...else if... else statements, everything works normally.

Is there a reason this is not a supported code model?

Posted by cohezive on 25-Oct-2013 14:51

That's the answer - and it also explains where equating another variable to nodeName and using toString method also do not  work.

var myvar  = root.nodeName -> Type of myvar:object

myvar.toString() -> Type of myvar.toString():object

To solve the issue, I had to cast the nodeName as a string -> Type of String(root.nodeName):string

Posted by Bill Wood on 25-Oct-2013 13:13

Yes, this is confusing.   Strict equality (===) vs Equality (==) produce different results when the Type of the objects do not match.  The SWITCH statement uses strict equality, and:

 typeof root.nodeName is 'object'

but

 typeof 'a' is 'string'.

If you run this code:

var xml="<a></a>";
var root = rbv_api.parseXML(xml);
var name = root.nodeName;
rbv_api.println("Root node name is: " + name);
rbv_api.println("typeof name is " + typeof name);
rbv_api.println("typeof 'a' is " + typeof 'a');
rbv_api.println("(Equality) Name=='a' " + (name == 'a'));
rbv_api.println("(Strict Equality) Name==='a' " + (name === 'a'));
switch (name) {
    case 'a': rbv_api.println("Root Node Match: " + name); break;
    case 'b': rbv_api.println("Root Node Match: " + name); break;
    default: rbv_api.println("Root name equality match is confusing");;
}

then the output would be:

Root node name is: a
typeof name is object
typeof 'a' is string
(Equality) Name=='a' true
(Strict Equality) Name==='a' false
Root name equality match is confusing

(Apologies for the earlier ".toString()" suggestion not working --- I ran into this years ago, and knew it was related to the string inequality, but forgot the specifics on how to solve it.   Note that the fastest way to cast the name as a string would be to add an empty string.... 
  var name = "" + root.nodeName;
(see http://jsperf.com/cast-to-string/2 for performance numbers)

All Replies

Posted by Laurent on 24-Oct-2013 11:42

I just tested the switch command on my instance and it works fine. Please note that the switch statement is case-sensitive. Could that be the issue?

Posted by cohezive on 24-Oct-2013 12:03

No, when I debug the output everything matched.  Also, I just copy/pasted the code into the if-then clause so it would have experienced the same issue.

Posted by Laurent on 24-Oct-2013 12:14

I tried the switch command in a deployed trigger and it's working fine for me. The following trigger is updating one of my Client fields to 'It works' if the record last name is 'Hatch' and 'It does NOT WORK' otherwise.

var nodeName = "{!lastName}";

switch(nodeName) {

 case 'Hatch':

   return 'It works';

   break;

 case 'MessageType2':

   // do something else

   return '???';

   break;

 default:

    return 'It does NOT WORK!';

}

Posted by cohezive on 24-Oct-2013 12:29

I am using the output from rbi_api.parseXML() - not a defined text value.  It doesn't matter if I reference the node attribute directly or copy it to a local variable.  The results are the same (pass thru to Default)

var code = rbv_api.getSharedValue("ReturnStatus");

 var body = rbv_api.getSharedValue("ReturnBody");

 var err = 0;

 var done = false;

 var root = rbv_api.parseXML(body);

 switch(root.nodeName){

   case 'RootNode1':

     // an error occured - to do add error parse

     rbv_api.println("Root Node Match: " + root.nodeName);

     var err = 1;

     done = true;

     break;

   case 'RootNode2':

     // may need to process

     rbv_api.println("Root Node Match: " + root.nodeName);

     break;

   default:

     // unexpected value - do nothing

     rbv_api.println("Invalid Root Node: " + root.nodeName);

     done = true;

 }

Posted by Bill Wood on 24-Oct-2013 13:24

I believe that the switch() statement and the if...then statement do have a difference in terms of supporting strict equality.  

Did you look at www.ecma-international.org/.../Ecma-262.pdf (see Section 11.9.6)

Usually it is a case of strict type matching that can cause this.   I have had trouble working with DOM objects in JavaScript with this issue, in part because things like NodeName return an attribute object.

If you tried    switch(root.nodeName.toString() )  you might get the behavior that you had when you defined the nodename as a var nodename.

Posted by cohezive on 24-Oct-2013 13:39

Thanks for the suggestion.  Unfortunately using the toString() method made no difference -

either in the switch statement

switch(root.nodeName.toString()) {

or by defining an separate variable and using that in the statement.

var myvar = root.nodeName.toString();

switch (myvar) {

Posted by Bill Wood on 25-Oct-2013 13:13

Yes, this is confusing.   Strict equality (===) vs Equality (==) produce different results when the Type of the objects do not match.  The SWITCH statement uses strict equality, and:

 typeof root.nodeName is 'object'

but

 typeof 'a' is 'string'.

If you run this code:

var xml="<a></a>";
var root = rbv_api.parseXML(xml);
var name = root.nodeName;
rbv_api.println("Root node name is: " + name);
rbv_api.println("typeof name is " + typeof name);
rbv_api.println("typeof 'a' is " + typeof 'a');
rbv_api.println("(Equality) Name=='a' " + (name == 'a'));
rbv_api.println("(Strict Equality) Name==='a' " + (name === 'a'));
switch (name) {
    case 'a': rbv_api.println("Root Node Match: " + name); break;
    case 'b': rbv_api.println("Root Node Match: " + name); break;
    default: rbv_api.println("Root name equality match is confusing");;
}

then the output would be:

Root node name is: a
typeof name is object
typeof 'a' is string
(Equality) Name=='a' true
(Strict Equality) Name==='a' false
Root name equality match is confusing

(Apologies for the earlier ".toString()" suggestion not working --- I ran into this years ago, and knew it was related to the string inequality, but forgot the specifics on how to solve it.   Note that the fastest way to cast the name as a string would be to add an empty string.... 
  var name = "" + root.nodeName;
(see http://jsperf.com/cast-to-string/2 for performance numbers)

Posted by cohezive on 25-Oct-2013 14:51

That's the answer - and it also explains where equating another variable to nodeName and using toString method also do not  work.

var myvar  = root.nodeName -> Type of myvar:object

myvar.toString() -> Type of myvar.toString():object

To solve the issue, I had to cast the nodeName as a string -> Type of String(root.nodeName):string

This thread is closed