Select to view content in your preferred language

arcade-bad-expression from valueExpression in UniqueValueRenderer

1130
8
Jump to solution
04-04-2023 12:04 PM
lawsonkendall
Occasional Contributor

I have a UniqueValueRenderer assigned to a StreamLayer, assigning "valueExpression" as shown: 

 

valueExpression: `
               const featureStartTime = $feature.START;
               const now = Date.now();
               const TIME_TO_LIVE = 90000;
               const timeSinceStart = now - featureStartTime;
               const veResult = (timeSinceStart > TIME_TO_LIVE) ? 'expired' : $feature.GROUP_NAME;
               return veResult;
            `,

 

 

 

 

 

 
'START' and 'GROUP_NAME' are attributes of the features produced by the StreamLayer.
 
My (Angular  15) application compiles without errors or warnings, but as soon as features begin streaming, the browser console shows an error from "esri.support.arcadeOnDemand":  'arcade-bad-expression', reporting UnexpectedIdentifier on the first line (declaration/assignment of "featureStartTime").
 
Can someone tell me what's wrong with my declaration of featureStartTime?  
 
Here is the error object, as copied from the browser console:

 

 

 

 

 

{
    "declaredRootClass": "esri.arcade.lib.parsingerror",
    "name": "ParsingError",
    "code": "UnexpectedIdentifier",
    "index": 22,
    "line": 2,
    "column": 22,
    "len": 15,
    "data": {
        "value": "featureStartTime"
    },
    "description": "Unexpected identifier",
    "range": {
        "start": {
            "line": 2,
            "column": 21
        },
        "end": {
            "line": 2,
            "column": 37
        }
    }
}

 

 

 

 

Note about Accepted Solution:  I accepted the solution based on the fact that it got rid of the error I report above.  Here is the final implementation, fully functional thanks to invaluable tips from @KenBuja and @AnneFitz , in case anyone is trying to solve a similar problem:

 

 

valueExpression: `
               var timeSinceStart = DateDiff(Now(), Date($feature.START));
               var veResult = IIf(timeSinceStart > ${TIME_TO_LIVE}, 'expired', $feature.GROUP_NAME);
               return veResult;
            `,
0 Kudos
1 Solution

Accepted Solutions
KenBuja
MVP Esteemed Contributor

Arcade is a basic language and doesn't understand "const". It only uses "var" to declare a variable. It doesn't understands the conditional statement as written. You'll have to replace that with an iif statement. I would recommend trying your expressions out in the playground to check your syntax

 

var featureStartTime = $feature.START;
var now = Date.now();
var TIME_TO_LIVE = 90000;
var timeSinceStart = now - featureStartTime;
var veResult = IIF(timeSinceStart > TIME_TO_LIVE, 'expired', $feature.GROUP_NAME);
return veResult;

 

 

View solution in original post

8 Replies
KenBuja
MVP Esteemed Contributor

Arcade is a basic language and doesn't understand "const". It only uses "var" to declare a variable. It doesn't understands the conditional statement as written. You'll have to replace that with an iif statement. I would recommend trying your expressions out in the playground to check your syntax

 

var featureStartTime = $feature.START;
var now = Date.now();
var TIME_TO_LIVE = 90000;
var timeSinceStart = now - featureStartTime;
var veResult = IIF(timeSinceStart > TIME_TO_LIVE, 'expired', $feature.GROUP_NAME);
return veResult;

 

 

lawsonkendall
Occasional Contributor

I copy/pasted your version of function (replace const with var; replace ternary with IIf) and I am now getting a new error:

"RemoteClient.js:1 [esri.views.2d.support.arcadeOnDemand] Feature arcade evaluation failed: Error: Execution error - Function not found".  

0 Kudos
AnneFitz
Esri Regular Contributor

Everything @KenBuja said is 100% right, thanks Ken! I also wanted to point out that Date.now() will not work in Arcade, instead use the built in Arcade function Now() . Also instead of subtracting the dates, I would use the built in DateDiff() function. Hope this helps!

KenBuja
MVP Esteemed Contributor

I also forgot to add that "now" is a reserved word and shouldn't be used as a variable name

lawsonkendall
Occasional Contributor

@KenBuja  @AnneFitz  -- Your combined suggestions got me past the errors that were being logged to the console.  I'm still not seeing the "expired" result being returned, even though I know I have expired features in the layer, but that's another problem.  You gave me the answer to fix the error I was seeing.  Thank you both very much.

 

As an aside, is there any way to console.log what the renderer is returning for "value" for any given feature?  I know I can't put a console.log inside of the valueExpression.

0 Kudos
KenBuja
MVP Esteemed Contributor

I used this script in the Playground to get "expired", using a Popup profile with its available fields. In the Playground, you can use Console to see intermediate variables.

var featureStartTime = $feature.LASTUPDATE;
var TIME_TO_LIVE = 90000;
var timeSinceStart = DateDiff(Now(), featureStartTime);
console(timeSinceStart, DateDiff(Now(), featureStartTime, "minutes"))
var veResult = IIF(timeSinceStart > TIME_TO_LIVE, 'expired', $feature.LASTEDITOR);
return veResult;

Note that anything more than about a minute and a half would be expired.

 

lawsonkendall
Occasional Contributor

so, in my running code, passing $feature.START to "console()" logs an epoch ms value, whereas passing result from call to DateDiff() is logging null for some reason.  Obviously, I'm hosing that somehow, but I feel like I'm closing in on this.

 

As far as I'm concerned, that "console()" function is the real breakthrough for me.  50% of my debugging is in the debugger and the other half is with console.log() statements.  You can't put a breakpoint in an Arcade expression, and I had no clue how to log the intermediate results.  I felt like a turtle on my back.  I feel like I have a chance to figure this out now.  Thank you for showing me that.

0 Kudos
lawsonkendall
Occasional Contributor

I see the problem.  Now() returns Date object, formatted according to locale, whereas $feature.START is a number -- epoch ms.  DateDiff() only takes Date objects for it's arguments, so I need to turn $feature.START into a Date before passing it to DateDiff().