If you haven't used callbacks before, you're in for a bit of a treat. ;-) The general idea is something like leaving a phone number instead of waiting. So, "Call me back at this number." That instruction gets passed into the asynchronous function.
In this case, we're saying do something (a function) when ready. That's the "callback".
The callback functions take an error (if any) and a response. Then, inside the callback function we decide what to do. Since we know we'll get a two-part reply (error, if any, and response), we get to name those inputs and deal with them by name inside the function.
In this example, https://github.com/ethereum/wiki/wiki/JavaScript-API#using-callbacks, the last argument is the callback. In that convention, the arguments all go into the function, including what to do with the reply. The last argument is a callback function. So, we're saying "Take the two-part response I know you'll return, and pass it into a function that looks like {this}
.
If I haven't completely lost you yet, we can adapt that pattern to the web3.eth.getAccounts()
function that returns an array.
// scope them up here so they're useful outside the callback
var accounts;
var defaultAccount;
web3.eth.getAccounts(function(error, response){
// this will wait for the response asynchronously
if(!error) { // error == 0, so let's process the response
console.log(response); // print it
accounts = response; // remember it
defaultAccount = accounts[0]; // do something with it
// carry on
} else {
console.error(error); // there was an error, so let's see it.
}
}) // notice how } marks the end of the function we passed IN to web3.personal.listAccounts() and ) marks the end of the request.
// whatever happens here WILL NOT WAIT for the callback to happen.
...
For things to unfold in a predictable (controlled) sequence, you have to nest inside callbacks. At // carry on
you can add something that should happen next. That leads to something called callback hell, meaning the nesting of the code gets unwieldy.
It's probably better to master it at this level before moving to a higher level of abstraction called promises that twists the syntax one more time.
Hope it helps.
Wrap the method invocation in a try/catch in your JS application to catch errors such as reverts thrown by solidity:
app.use('/api', function(err, req, res, next) {
try {
// add your smart contract function call here
next()
} catch(err) {
// handle error here
next(err)
}
})
Best Answer
Turned out I shouldn't have used the callback in this case. Here's the working code: