Promise in Js

With Ken and Barbie

Created by Fabien Garcia

What is a promise?

a declaration that something will or will not be done, given, etc., by one

dictionary.com

The story of ken and barbie

Let's take Ken and Barbie:


ken = new PerfectMan()
barbie = new PerfectWoman()
          

They met and ken propose to barbie

So this is the classic process


ken.marry(barbie)
          

But what happen for real?


ken.marry(barbie)
  .then => ken.find(job)
  .then => child = Sex(ken, barbie)
  .then (child) => ken.takeCare(child); barbie.takeCare(child)
  .then => ken.die()
  .then => barbie.die()
          

The story of normal people

Have you met Ted?


ted = new Man()
robin = new Woman()
            

Ted want to marry but Robin not really ...

What happen when they met?


ted.marry(robin)
  .then => ted.find("job")
  .fail => robin = ted.find("otherWoman")
  .then => child = Sex(ken, robin)
  .then (child) => ken.takeCare(child); robin.takeCare(child)
  .then => ken.die()
  .then => barbie.die()
  .fail => HIMYM = Factory("serie")
            

If you want to have barbie


me = new Man()
barbie = new PerfectWoman()
          

you are not Ken, so you will have to work hard


$.when(me.find("job"), me.do("sport"), 
  me.earn("money"), me.do("surgery"))
  .then => me.marry(barbie)
  .then => child = Sex(me, barbie)
  .then(child) => me.takeCare(child)
  .then => me.die()
  .then => barbie.die()
  .fail(error) => me.find("otherWoman")
            

So what is the link with JS?

It's the same thing!

Code is just a story

Some examples

Classic workflow in node


user.findWhere(name:"john").success(user) ->
  Email.send(user.email).success(response) ->
    fs.write response, (status) ->
      user.save(status: "message send"). success(err, res) ->
        console.log "workflow finished"
          

It will be


user.findWhere(name:"john")
  .then (user) -> Email.send(user.email)
  .then (response) -> fs.write response
  .then (status) -> user.save(status: "message send")
  .then (status) -> console.log "Workflow finished" 
          

If you need data in several place

Example with backbone


checkAllFetched = (collection) =>
  collection.fetched = true
  if @collection1.fetched and @collection2.fetched
    @prepareData()
fetchOptions =
  success: checkAllFetched
  data: @params
@collection1.fetch fetchOptions
@collection2.fetch fetchOptions
            

turn with promise


$.when(@collection1.fetch(data: @params), 
  @collection2.fetch(data: @params))
  .done => @prepareData()
            

How to convert into a promise?

With Q

classic database search with node


find: (email, callback) ->
  @query "SELECT `id`, `email` WHERE email = `?` LIMIT 1", email, (err, res) ->
    callback err, res[0]
            

Turn into promise


find: (email) ->
  deferred = Q.defer()
  @query "SELECT `id`, `email` WHERE email = `?` LIMIT 1", 
    email, (err, res) ->
    if err
      deferred.reject new Error(err)
    else
      deferred.resolve res
  return deferred.promise
          

shorter notation


find (email) ->
Q.nfcall @query, "SELECT `id`, `email` WHERE email = `?` LIMIT 1", email 
            

or


find (email) ->
Q.ninvoke @, "query", "SELECT `id`, `email` WHERE email = `?` LIMIT 1", email 
            

How to convert into a promise?

With jQuery

It is here since jQuery 1.5

With the object defered

Turn async function into promise


promiseFunc = ->
  deferred = new jQuery.Deferred()
  ayncFunction param, (err, res) ->
    if err
      deferred.reject err
    else
      deferred.resolve res
  return deferred.promise()
            

It will be used


$.when(promiseFunc).then ((res) ->
  alert status + ", things are going well"
            

With existing jQuery method


$.when($.get("http://url.com"))
  .then (data) ->
    alert data + ", things are going well"
  .fail (err) ->
    console.log err
            

Links

Question?

THE END

BY Fabien Garcia