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?
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
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)
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?
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.
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!';
}
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;
}
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.
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) {
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)
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