Before v2.0.0 stable, object macros parsed by RiveScript should be loaded in as async functions so that they may make use of the await keyword themselves.
Note: because this could be backwards-incompatible (imagine a Node 6 environment trying to parse an async function and failing), RiveScript should test for async/await support in the environment first.
e.g. wrap a try/catch around eval("(async function() {})"), and if it fails, parse the object macro as a standard function as we've been doing previously.
In case an object macro uses the await keyword and your environment doesn't support async/await: the macro will fail to parse and log the syntax error, as would be expected. Macros that want to be backwards compatible can deal with Promises instead of using await, and normal string-returning macros will work all the same.
Example use case:
// This bot will detect if the user ever sends an identical message
// twice, even if they send other things in between.
> begin
+ request
* <call>is-repeating</call> == true => {random}
^ You already said that.|
^ Not again.|
^ No more saying "<get origMessage>"{/random}
- {ok}
< begin
// Because the object macro isn't async, Promises are a pain to deal with.
> object is-repeating javascript
var user = rs.currentUser();
return new Promise(function(resolve, reject) {
// Get the user's original message.
rs.getUservar(user, "origMessage").then(function(origMessage) {
// Get the map where we store repeated triggers for the user.
rs.getUservar(user, "repeat-map").then(function(map) {
// Check if the map was initialized; create it if not.
if (typeof(map) !== "object") {
map = new Object();
}
// Has the user already sent this message?
if (map[origMessage] !== undefined) {
return resolve("true");
}
// Store this in the map.
map[origMessage] = true;
rs.setUservar(user, "repeat-map", map).then(function() {
resolve("false"); // they were not repeating themselves just now
});
});
});
});
< object
Whereas if the object macro was async, the code could resemble its v1.19.0 working counterpart:
> object is-repeating javascript
var user = rs.currentUser();
var origMessage = await rs.getUservar(user, "origMessage");
var map = await rs.getUservar(user, "repeat-map");
// Check if the map was initialized; create it if not.
if (typeof(map) !== "object") {
map = new Object();
}
// Has the user already sent this message?
if (map[origMessage] !== undefined) {
return resolve("true");
}
// Store this in the map.
map[origMessage] = true;
await rs.setUservar(user, "repeat-map", map)
resolve("false");
< object
Effects
Macros that currently return strings (synchronously) will get their result automagically wrapped in a Promise because of the async function, but this should be fine, async macros work great nowadays.
Macros that explicitly return Promises still work fine.
But now macros are able to use the await keyword and simplify their async logic.
Before v2.0.0 stable, object macros parsed by RiveScript should be loaded in as
async function
s so that they may make use of theawait
keyword themselves.Just add the word
async
in the function declaration here: https://github.com/aichaos/rivescript-js/blob/817c9d0eb106f0ee3e7974bf9e38f413d8436f7d/src/lang/javascript.js#L40Example use case:
Whereas if the object macro was async, the code could resemble its v1.19.0 working counterpart:
Effects
async function
, but this should be fine, async macros work great nowadays.await
keyword and simplify their async logic.