Callbacks & return values
JavaScript — and Playground — are mostly asynchronous.
This means that when you call an operation, it starts in the background immediately, and your program continues running without waiting for the result.
This can cause trouble if you depend on that result. For example, imagine you want to:
Get an avatar’s UUID
Use that UUID to find the avatar’s age
Finally, send the age to another avatar
Important update:
As of October 2020, Bot Playground commands support the await instruction.
It’s recommended for most cases, as it makes scripting much easier!
See Async and await for examples.
Starting from Scratch
To start, use the name2key bot command:
Bot.name2key("Glaznah Gassner");Okay, we know how to ask the question. But how do we get the reply?
Way 1: Using Callbacks
The simplest way is to use callback functions:
var slname = "Smartbots Resident";
Bot.name2key(slname, function(result) {
console.log("Got the UUID!", result.slkey);
// Oh, now the next step, also with a callback
Bot.avatarProfile(result.slkey, function(result2) {
console.log("Got the age!", result2.age);
Bot.im("Glaznah Gassner", "The age of " + slname + " is " + result2.age);
});
});
console.log("I've asked for UUID and now waiting for answer");Looks a bit weird, right?
Imagine adding a third callback level — this is called callback hell.
Way 2: Promises
To avoid callback hell, Bot Playground supports the Promise object.
Here’s how it works:
var slname = "Smartbots Resident";
Bot.name2key(slname)
.then(function(result) {
// this code will be called when name2key() gets completed
console.log("Got the UUID!", result.slkey);
// Oh, now the next step
return Bot.avatarProfile(result.slkey);
})
.then(function(result2) {
// this code will be called when avatarProfile() gets completed
console.log("Got the age!", result2.age);
Bot.im("Glaznah Gassner", "The age of " + slname + " is " + result2.age);
});
console.log("I've asked for UUID and now waiting for answer");Much easier, right?
Each command (name2key, avatarProfile, etc.) returns a Promise object.
You can call its .then() function to set your handler — it runs once the command completes.
Subsequent commands can be chained as shown above.
Note the return Bot.avatarProfile() — this ensures the next .then() is chained to it.
Breaking the Promise Function Chain
What if you need to break the chain — for example, when a recipient UUID cannot be found?
var slname = "Smartbots Resident";
var all_money = 0;
var uuid = "";
// we want to send money to avatar
Bot.name2key(slname)
.then(function(result) {
// Oh-oh, a name mistake!
if (!result.success) { throw "Unknown recipient!"; }
// we know the recipient's UUID now
uuid = result.slkey;
return Bot.getBalance();
})
.then(function(result) {
// we know our balance now
all_money = result.balance;
Bot.giveMoney(uuid, all_money);
})
.catch(function(error) {
// this code will be called when something wrong happened with a command
console.log("We've faced an error: " + error);
})
.then(function() {
// Stop our script at any case
console.log("Script has been finished");
exit();
});We added two important parts:
if (!result.success) { throw "Unknown recipient!"; }and
.catch(function(error) {
console.log("We've faced an error: " + error);
});Throwing an error cancels all further operations until the .catch() block.
If everything succeeds, .catch() is skipped.
The .then() block after .catch() runs regardless,
making it perfect for cleanup or stopping your script.
More Examples
Check Examples for more scripts to experiment with.