from the examples provided here and here
They show creating a request and then attaching the onerror
and onsuccess
handlers after the request
If I understood your question, then in order for you to start understanding the answer, you need to learn about or review asynchronous javascript. If you already know this stuff, sorry, but it looks to me like if you knew this, you would easily answer your own question.
The classical training says that in the following code, the second statement comes after the first statement, at a later time:
var x = 1;
var y = 2;
console.log('%s %s', x, y);
However, that is actually a simplification of what is really happening. Essentially, there is a hidden process in the Javascript engine, called the event loop. Each iteration through the loop executes a series of statements. These statements execute serially (in order), and technically at slightly different times.
However, from the perspective of concurrency, they are occurring at the same time. This co-occurrence of the several statements in a particular pass of the event loop can be called an epoch, or time period, or something to that effect. This can also essentially be understood as synchronous code.
Asynchronous code works quite differently. In essence, when you initiate a call to an asynchronous function, you are not waiting until that function returns. The rest of the code (the later statements) that are within the same epoch (described above) are also executed. The function call will eventually complete, but this will only occur in a later epoch (the next pass of the event loop, or some pass thereafter).
Let's approximate how things would work asynchronously:
var x, y;
setTimeout(function eventuallyRunMe() {
x = 1;
y = 2;
}, 1);
console.log('%s %s', x, y);
In the first epoch, the variables are declared, they have no values assigned, and a call to setTimeout executes. Then, the epoch completes, and the next epoch starts. The JS engine checks if 1 second has elapsed. Let's assume it does. Then, the JS engine calls eventuallyRunMe from start to finish. The function assigns values to x and y in the outer scope. Then, for the remainder of this second epoch, and for all future epochs, x and y have values.
So, if you were to run this code, then in the synchronous example, you would see the values of x and y printed to the console. In the asynchronous example, you would see undefined. This is because the call to console.log happens in the same epoch as the declarations and assignments in the synchronous example, but not in the same epoch as the assignments in the asychronous example.
Now, look at the code in your example:
var transaction = db.transaction(...);
transaction.oncomplete = function() {};
transaction.onerror = function() {};
As you noticed, the code works regardless of the order of these statements. That is correct. The statements are associative. The order isn't important. That is because these statements are just synchronous registrations of asynchronous callbacks. The call to db.transaction
does not actually go and immediately open the transaction in the same epoch. It does immediately create a variable to reference the transaction, and it does immediately create a transaction object, but it doesn't necessarily start running the transaction's put/get/openCursor requests. Nothing happens at all immediately. Only at the very end of the epoch does anything start happening. At the end of the epoch (or the start of the next, whatever you think is easier to understand), the underlying JS engine goes back and looks at what is registered to execute, and then executes everything nearly all at once. Then the next epoch of the JS event loop starts, and if the calls have completed at that point, callback functions are called and so forth.
This is a simplification of things, and informal, and I am sure someone who is an expert wants a more accurate explanation, but I hope it was helpful in getting you to understand how the order isn't important.