Promise is not part of the javascript environment

I’m using openHAB 3.0 with docker on a linux host OS.

I wanted to wait in an ECMA script rule some time and used the standard approach of promises and setTimeout to implement that. Unfortunately Promise seems not to be part of the javascript environment.

To illustrate I created a rule with a simple ECMA script:

var logger = Java.type("org.slf4j.LoggerFactory").getLogger("org.openhab.core.model.script.PromiseTest")

function sleep(sleepTime) {
  return new Promise(
    function(resolve, reject) {
      setTimeout(resolve, sleepTime);
    }
  );
}

sleep(1000).then(
  function() {
    logger.info("Slept well for one second");
  }
);

When I run the script from the rules editor I get the following error in the log file:

2021-01-01 14:52:31.894 [ERROR] [internal.handler.ScriptActionHandler] - Script execution of rule with UID 'd169586413' failed: ReferenceError: "Promise" is not defined in <eval> at line number 4

Is this a bug?

I think that is in ES6 What Javascript version has OH 3 targeted?

Something like Babel may compile it down to ES5 syntax.

When creating rules from the main UI, the script type selection dialog says, that it is ECMA 262 Edition 5.1. This is pretty old (from 2011). And you are right, promises were introduced in version 6.

1 Like

You will also find that setTimeout is not defined:

var OccupationDelayTimer;

events.postUpdate(‘OccupancyStatus’, ‘Script Entered’);
OccupationDelayTimer = setTimeout(waitToChangeOccupancy, 3000);
events.postUpdate(‘OccupancyStatus’, ‘setTimeout Called’);

function waitToChangeOccupancy()
{
events.postUpdate(‘OccupancyStatus’, ‘Unoccupied after 3 secs’);
}

2021-01-01 15:33:49.793 [ERROR] [internal.handler.ScriptActionHandler] - Script execution of rule with UID ‘8b2f94c2e1’ failed: ReferenceError: “setTimeout” is not defined in at line number 4

Which is a bit of a pain, so is there an alternative way to forefill the actions of setTimeout or will I have to go back to writing scripts in Rule DSL and use createTimer?

Which is a bit of a pain, so is there an alternative way to forefill the actions of setTimeout or will I have to go back to writing scripts in Rule DSL and use createTimer?

For just waiting, there is an alternative as I described here:

And there is more to know. Each rule action script gets a local context. You can store variables in there and they survive until you edit or update the rule. If you edit or update the rule, the context is cleared.

The context can be accessed by the this object from within the script. So something like this should work:

'use strict';

var logger = Java.type("org.slf4j.LoggerFactory").getLogger("org.openhab.core.model.script.HelloWorld");

if (this.myVar === undefined) {
  this.myVar = 'Hello, world';
  logger.info("this.myVar set to {}", this.myVar);
}

logger.info("this.myVar has value {}", this.myVar);

If you run this script for the first time, you see the log output that myVar was set. In the next runs you will notice, that this.myVar is still available. But if you change the script and save it, the context is lost.