SQLite and Callbacks
- Next step is to add a real DB to the
ExpressMVC
example.
- Look at
ExpressMVCSqliteCallbacks
.
- Includes the
sqlite3
module
- Main feature of sqlite3 is that it stores the DB in a local file.
- Not performant/scalable; but simple and useful for sample code.
- Look at
SqliteToyDB.js
initialize
run 3 SQL commands (a CREATE and two INSERTS).
(In other words, it creates and populates the db)
all
runs a SELECT that grabs all Toys in the DB.
find
runs a SELECT that looks for a specific toy.
- Sqlite calls return data using callbacks only.
The return value of the method does not contain the requested data.
- run
callbacksRequired.js
- Notice that the return value is a DB object, not the requested toys.
- Notice that the code after
db.all
runs immediately and results in output
before the results of the query are printed (even though the code to print
the results comes first in the source code).
- Key idea: DB calls take awhile. We don’t want to “block” (pause the CPU/Core/Thread)
and just wait. Instead, specify the code to run when the data is ready, then move on and
get something useful done.
- Show the controller (in
index.js
)
- Notice the workflow. (This is not obvious, and may take a minute to figure out.)
- There are two levels of callbacks. On the one hand, this technically doesn’t matter:
You should be able to treat the
allToys
method as a “black box” and not concern yourself
with how it works. On the other hand, you may have to write code like this yourself someday, so let’s take a look.
- At the top level, the interface/contract for
allToys
says that you pass it a function that expects an array of Toy
s as input, and it will call that function when the list of toys is ready.
(Not too bad: Array of Toy
s appears as if by “magic” and you build a web page from it.)
- But, let’s see how the sausage is made. Look at the implementation of
allToys
. The list of toys comes from the DB. Specifically, it comes from a call to the Database’s all
method, which run the specified SQL statement. This method also returns data using a callback. This particular callback function receives two parameters: (1) an object describing any errors, and (2) an Array containing the rows returned by the SQL statement.
- Notice that the rows returned by the DB are not
Toy
objects. They are just generic objects that map column names to the value for that column.
- We must write “glue” code that transforms these “generic” objects into our ‘Toy’ objects.
- In this case, the “glue” is trivial: a
map
that passes the generic object into the Toy
constructor.
- Once this list of actual
Toy
objects exists, we want to pass it to the original callback.
That callback was stored in a local parameter named (imaginatively) callback
. So we execute that function and pass the list of Toy
s.
- The end result is a callback nested within another callback.
- Nested callbacks are a slippery slope that lead to “callback hell”.
- See
SqliteToyDB#extremes
for an example. (Pretend for sake of the “story” that the two SQL statements can’t be combined.)
- Now imagine this code with error handling at each level!
- «http://callbackhell.com/»