- Introduction to Custom Roll Parsing
- The Structure of a Custom Roll Parsing Function
- The CRP Roll String And Many Buttons
- startRoll and Analysing Your Dice
- Changing Attributes with Custom Roll Parsing
- Using Queries in Custom Roll Parsing
- Computed Properties and CRP Roll Templates
- Callbacks and Promises with startRoll
- Action Buttons and the MacroBar
This describes an optional feature of startRoll
. It’s not necessary to know this. Future examples will not use it, but if you want to use it in your own code, you can.
Much of Roll20’s sheet worker code is based on asynchronous functions. getAttrs, setAttrs, getSectionIDs,
and also startRoll
and finishRoll
are callback functions. The following code should be familiar:
getAttrs(['an_attribute'], values => {
const score = +values.an_attribute || 0;
});
Code language: PHP (php)
In this code, values
is the callback. It is created by the getAttrs
function, and only exists inside the function. In the following code, an undefined
value would be sent to the console.
getAttrs(['an_attribute'], values => {
const score = +values.an_attribute || 0;
});
console.log(values);
Code language: JavaScript (javascript)
At the time that console
command is run, the getAttrs
function has finished, and values
is no longer defined. To make that code work, you’d have to do this:
getAttrs(['an_attribute'], values => {
const score = +values.an_attribute || 0;
console.log(values);
});
Code language: JavaScript (javascript)
The values
callback only exists inside the getAttrs
function.
Modern JavaScript uses a feature called Promises. A promise is a function that waits for a result, and would look like this:
const values = await getAttrs(['an_attribute'], values);
const score = +values.an_attribute || 0;
console.log(values);
Code language: JavaScript (javascript)
Using the await
keyword tells roll20 to stop the code here and wait for a result, then proceed. You can create linear code that is easier to read and write.
Notice that you assign the promise function to a variable. Instead of creating a callback variable named values
, we create a normal variable called values
, and can then use it just like any other variable.
startRoll: Async and Await
At the moment, Promises are only available for the startRoll
function. You can’t do this with any other function.
You must also tell roll20 that the following code includes a Promise with the async
keyword, like this:
on('clicked:simple', async () => {
const roll_high = await startRoll('%{template:default} {{name=Roll High}} {{roll=[[{1d10,1d8,1d6}kh1]] }}')
finishRoll(roll_high.rollId);
});
Code language: JavaScript (javascript)
Use async
in the last function that contains the startRoll
function. So if you used getAttrs
, that would look like this:
on('clicked:simple', () => {
getAttrs(['an+attribute'], async values => {
const roll_high = await startRoll('%{template:default} {{name=Roll High}} {{roll=[[{1d10,1d8,1d6}kh1]] }}')
finishRoll(roll_high.rollId);
});
});
Code language: JavaScript (javascript)
Elegance vs Complication
I tend not to use the promise version of startRoll
, and I won’t usually be using it in this series. It is better code, but it also creates complications. You have to remember to include the async
keyword and might have to place it in a different place depending how your function is built. Also, you have a bunch of functions that should be written this way but cannot, like getAttrs
and setAttrs
, so you have to remember two different ways of writing your functions.
If roll20 ever upgrades those other functions to use promises, i will switch to this method immediately because the code is more elegant. But right now it creates unneccessary complications.
There are rolls where I do find it worth using, and I will include one of those for sake of example. But if you like them, by all means use them.