Hey there folks! This year I'm going to be trying to give a weekly recap of what's going on in the Lift world,
with a particular eye on Lift 3 development. It's been going on relatively behind the scenes so far, and there
are goodies in there that haven't been shared widely enough. There's also been some forward development
and bug fixes in the 2.6 world, though those are more often mentioned here on the list. Either way, I wanted
to start putting together a weekly blurb that would give a quick recap of interesting developments in the
repository as well as, when I spot them, particularly interesting discoveries or tidbits from the Lift list and
elsewhere in the Lift-a-verse. If you have any ideas for things that might be mentioned in something like this,
drop me a line at savedfastcool AT
gmail.com !
The shape of the recap will probably change over time. Super-long list posts like this aren't an ideal medium
IMO, but I didn't have a site to put this under yet, and I wanted to get it going instead of putting the site
and design and whatever else before the actual content that would be useful to folks.
For the first few weeks, I'll be trying to cover some of the stuff that's already gone into Lift 3 and Lift 2.6
(which is currently at 2.6-M1, doncha know). Today, we'll look at LAFuture.
Lift 3 and Lift 2.6-M1 add a set of methods to LAFuture to make them usable in for comprehensions.
In particular, LAFuture now implements map, flatMap, filter, and withFilter. This means you can now do
something like this:
val facebookUser: LAFuture[FbUser] = getFbUser
for {
user <- facebookUser
firstName <- user.firstName // LAFuture[String]
lastName <- user.lastName // LAFuture[String]
name = firstName + " " + lastName
avatar <- user.avatar // LAFuture[String]
if ! avatar.isEmpty
} yield {
"img [alt]" #> name &
"img [src]" #> avatar
}
(Provided, of course, that you have an API structured this way ;) )
Secondly, you can now specify the LAFuture's scheduler when creating the future. This is likely to be useful
in relatively few standard cases, but may be useful for testing. The default scheduler is LAScheduler, and
is what was always being used as the scheduler before.
LAFuture also now supports callbacks, installable by invoking onSuccess, onFail, and onComplete.
Before this, LAFuture was mostly used by invoking .get(<timeout>) on it in a thread fired up using
Schedule.schedule or something of the sort. Now you can set up an LAFuture, install a completion handler,
and let it do its thing. This can be particularly useful in comets, for example:
def lowPriority = {
case ShowName =>
facebookUser.flatMap(_.user.firstName).onSuccess(firstName => this ! PushName(firstName))
}
You can also chain these together:
def lowPriority = {
case ShowName =>
facebookUser.flatMap(_.user.firstName)
.onSuccess(firstName => this ! PushName(firstName))
.onFail(_ => partialUpdate(Call("facebookError()").cmd)
}
The LAFuture singleton now has a build function, which can be used to build a future around a
call-by-name value, say if you expect a user lookup operation to take a while:
val eventualDbUser = LAFuture.build(getLatestUser)
for {
dbUser <- eventualDbUser
fbUser <- dbUser.fbUser
...
Last but not least, the LAFuture singleton now also has an observeCreation function. This lets you
hook in and find out when a future is created on the current thread. This doesn't necessarily mean
the future will be satisfied on the current thread, but it has to be created on it. No clear examples
from me for this one, but if you come up with one please pass it on!
That's it for this time; next time, we'll have a quick look at some compatibility-breaking things in Lift 3
and the new Markdown support in Lift 2.6-M1/3.0.