Callbacks and return values
Javascript is mostly asynchronous language, and Bot Playground too. This means that when you call an operation, it starts at the background immediately, and your program continues running without waiting for the result.
This may cause troubles if you need that result. For example, imagine we want to:
- get an UUID of avatar
- using that UUID, know the age of avatar
- finally, send the age to another avatar.
Important update
As of October 2020, Bots Playground commands support await instruction. It is recommended and makes scripting easier!
See Async and await for examples.
Starting from scratch
To start, we use name2key bot command:
Bot.name2key("Glaznah Gassner");
Okay, we know how to ask the question. 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. Imagine we want to add the third callback level? This is called a callback hell.
Way 2: Promises
To get rid of callback hell, Bot Playground supports a Promise object. This is how it looks like:
var slname = "Smartbots Resident";
Bot.name2key(slname)
.then(function(result) {
// this code will be called when name2key() get completed
console.log("Got the UUID!", result.slkey);
// Oh, now the next step
return Bot.avatarProfile(result.slkey);
})
.then(function(result) {
// this code will be called when avatarProfile() get 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");
Looks a bit easier? Each command (name2key, avatarProfile and others) returns a special object, Promise. You can call its then() function and set your handler. It will be executed as soon as command completed.
Subsequent commands can be chained like example above. Note that we've added a return Bot.avatarProfile() so next .then() get chained to the avatarProfile command.
Breaking the promise function chain
What if you want to break the chain? Imagine the following code:
var slname = "Smartbots Resident";
var all_money = 0;
var uuid = "";
// we want to send money to avatar
Bot.name2key(slname)
.then(function(result) {
// we know the recipient's UUID now
uuid = result.slkey; // <== a potential problem here if we can't find a recipient's UUID
return Bot.getBalance();
})
.then(function(result) {
// we know our balance now
all_money = result.balance;
Bot.giveMoney(uuid, all_money);
})
.then(function() {
// Stop our script
console.log("Script has been finished");
exit();
});
What if we won't find a recipient (an account deleted or name typed wrongfully)? We want to bail our at the very first .then(), right? This is when .catch() helps:
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 pieces of code:
if(!result.success) { throw "Unknown recipient!"; }
and
.catch(function(error) {
// this code will be called when something wrong happened with a command
console.log("We've faced an error: " + error);
})
The first line of code throws an error and cancels all further operations until the .catch() block (if all operations complete successfully, the .catch() block will be just skipped).
Note that .then() block after a .catch() will be executed at any case - just because it stands after the catch.
More examples
Check Bot Playground Examples for more code to play with.