Now, one of the things that you might have noticed is every single time we call one of these functions 1
topUp or withdrawl, it seems to take an absolute age for it actually to be implemented. 2
All I want to do is subtract 1o from 100. 3
Why did it take a good 3 seconds for this to happen? 4
And the reason for this is because these methods, topUp and withdrawal, in ICP lingo, is known as an 5
update method, because what it's doing is it's updating the state of some sort of variable within our 6
canister. 7
So in this case, it's updating what's held inside this currentValue. 8
And that means we're going to have to write to the blockchain, which means it's a more computationally 9
expensive operation, 10
so that's why it takes a bit longer for it to actually happen. 11
Now, very often when we're writing code, say we're building a game or something that requires sort 12
of a live update, 13
we don't really have the time to wait for that. 14
But in those cases, usually we're not trying to update any sort of state. 15
We're just trying to get its value to read the value of a variable. 16
So in these ICP canisters, they differentiate between what's called query and update methods. 17
So query calls basically allow the user to query the current state or some piece of state within the 18
canister without changing it. 19
So as long as you're not trying to change a variable or update the state of something, then you can 20
use these ultra fast query calls. 21
And if you wanted to, however, actually update the state, then this is going to happen much slower 22
and then you actually use what's called an update call. 23
So how do we create a query call? 24
How do we make sure that we actually tap into this ultra-fast read-only methods? 25
Well, again, we have our public func. 26
But in addition, we add another keyword which is called query and that goes before the func keyword. 27
Then we get to name our function, which I'm just going to call checkBalance, because that's what 28
we want to do. 29
We want to be able to check what's currently held inside this variable, currentValue. 30
And you'll notice that I'm getting an error here because I haven't actually capped off my previous function. 31
So unlike JavaScript, in Motoko, there has to be a semicolon between all of the function declarations. 32
So there's one here between these two, 33
and I have to add this one here between these two for that error to go away. 34
Now, if it happens to be the final one, then you don't have to add it. 35
But I think just for consistency sake, it's usually a good idea to add a semicolon at the end of each 36
function. 37
Now inside checkBalance, 38
what we want to do is we want it to return an output. 39
So we want it to look inside our container and tell us what is the value of this variable. 40
So over here, in order to specify that this function is going to have a return value, 41
we just have to add a colon and then the data type of the output, which in this case is a natural number. 42
So I'm going to write Nat right here. 43
In addition to returning a natural number, you can see that I have an error here because it says the 44
shared query function must have syntactic return type of async and then some sort of type. 45
So basically whenever you have a function that has an output, the output has to come out asynchronously. 46
What does that mean? 47
A good analogy for synchronous and asynchronous when it comes to computer programs is you can imagine 48
a synchronous program running like trains on a single track. 49
So this first train has to move before the second train can actually go anywhere. 50
This is synchronous. 51
There's only a single track for the programs to execute. 52
Each operation has to happen before the next one can go. 53
Now, when it comes to asynchronous, it's almost like we have multiple tracks and the trains are kind 54
of freed from each other. 55
They can go whenever they need to at their own pace. 56
Now, when it comes to actually seeing synchronous and asynchronous in real life, you can imagine the synchronous 57
as your dialup modem that's loading up each image on the website one by one, and nothing really can 58
happen until everything's been loaded. 59
So you, as the user can't interact with the website, you can't click away, you can't click on a new 60
link before everything is done. 61
It's basically frozen until everything is loaded up. 62
When it comes to asynchronous loading on the web, this is what we see every day on the modern web. 63
When you hit load, you can see these different images and different components can load in their own 64
time. 65
This GET request is shot out to all of these different resource locations and then the resources can come 66
back once they're actually done and show up on screen in no particular order. 67
This means that it frees up the user interaction with the website so you can click away on a link even 68
before all the photos are loaded. 69
And it also means that the fastest processes are not being held up by the slowest ones. 70
Coming back to our function, 71
the return from a function inside the canister has to be asynchronously returned. 72
So that's why we're adding that keyword here. 73
So it's the async keyword and then the data type. And now we have to actually specify what is going 74
to be returned. 75
So we're going to use the return keyword and then we're going to say, well, let's return the current 76
Value. 77
This is basically just a read-only operation; we're not modifying any variable 78
in here. We're not changing anything's state. 79
And what this allows us to do is to quickly get the value of this variable. 80
And you can see once I go ahead and deploy this, just how quick these read-only query functions are. 81
So let's go ahead and refresh our candid UI. 82
You can see we've got our new function, which is called checkBalance, and this one has a query button 83
associated with it. 84
So if I go ahead and press on it, you can see that it gives me the value of my currentValue 85
and that happened in 0.014 seconds. 86
Now, in comparison, if I decided to call a update function, for example, our topUp or withdrawl 87
and I hit call, 88
you can see this takes something like around 2 to 3 seconds, 89
so in this case, 2.14 seconds. 90
And this is the difference between the query functions and the update functions. 91
And this is something really important to be aware of when you are writing applications for the Internet 92
computer. 93
To really leverage this really quick ability to read the state of your application. 94
If you want to read up more on it, I will link to this page in the documentation where it talks a bit 95
more about the difference between query and update methods. 96
But the main part you have to understand is that the update calls will go via the blockchain, so it 97
will require consensus, which is why it takes a long time. 98
The query calls are adapted to not actually require to modify anything on the blockchain. 99
So it can be super, super fast. 100
You can read things from your application very quickly. 101
Now, in the next lesson, I want to talk about this idea of orthogonal persistence that is available 102
to us in the Internet computer so that we can see how state is preserved between different updates of 103
our cannister. 104
So for all of that and more, 105
I'll see you in the next lesson.