javascript promises

22
JavaScript Promises @tomaszbak

Upload: tomasz-bak

Post on 15-Jul-2015

276 views

Category:

Software


0 download

TRANSCRIPT

JavaScript Promises@tomaszbak

user = getUser(id)

console.log(user.name) # won’t work if getUser() is async

user = getUser(id)

console.log(user.name) # won’t work if getUser() is async

# callback

getUser id, (user) -> console.log(user.name)

user = getUser(id)

console.log(user.name) # won’t work if getUser() is async

# callback

getUser id, (user) -> console.log(user.name)

# promise

getUser(id).then (user) -> console.log(user.name)

Promises/A+

The Promise interface represents a proxy for a value not necessarily known when the promise is created. It allows you to associate handlers to an asynchronous action's eventual success or failure.

Source: https://developer.mozilla.org/en/docs/Web/JavaScript/Reference/Global_Objects/Promise

Promises/A+ states

pending initial state, not fulfilled or rejectedfulfilled successful operationrejected failed operationsettled the Promise is either fulfilled or

rejected, but not pending

Source: https://developer.mozilla.org/en/docs/Web/JavaScript/Reference/Global_Objects/Promise

Source: https://developer.mozilla.org/en/docs/Web/JavaScript/Reference/Global_Objects/Promise

Execute in sequencegetUser(id) (user) ->

getNewTweets user, (tweets) ->

updateTimeline(tweets)

Execute in sequencegetUser(id) (user) ->

getNewTweets user, (tweets) ->

updateTimeline(tweets)

getUser(id).then (user) ->

getNewTweets(user).then (tweets) ->

updateTimeline(tweets)

Execute in sequencegetUser(id) (user) ->

getNewTweets user, (tweets) ->

updateTimeline(tweets)

getUser(id).then (user) ->

getNewTweets(user).then (tweets) ->

updateTimeline(tweets)

getUser(id)

.then(getNewTweets)

.then(updateTimeline)

Execute in paralleltmp = []

$http.get('/app/data/first.json').success (data) ->

tmp.push data

$http.get('/app/data/second.json').success (data) ->

tmp.push data

$http.get('/app/data/third.json').success (data) ->

tmp.push data

$scope.combinedNestedResult = tmp.join(', ')

Execute in parallelfirst = $http.get('/app/data/first.json')

second = $http.get('/app/data/second.json')

third = $http.get('/app/data/third.json')

$q.all([first, second, third]).then((result) ->

[result[0], result[1], result[2]]

).then (tmpResult) ->

$scope.combinedResult = tmpResult.join(', ')

Promise can be cachedgetUser: (id) ->

@users ||= {}

@users[id] ||= Api.getUser(id)

then(successCallback, errorCallback, notifyCallback)

updateUser().then(

(res) -> console.log 'Success'

,

(err) -> console.log "Error: #{err}"

,

() -> console.log 'Finally'

)

Source: https://docs.angularjs.org/api/ng/service/$q

catch(errorCallback) == promise.then(null, errorCallback)

finally(callback, notifyCallback)

updateUser()

.then (res) -> console.log 'Success'

.catch (err) -> console.log "Error: #{err}"

.finally -> console.log 'Finally'

Source: https://docs.angularjs.org/api/ng/service/$q

ImplementationsjQuery.promise()

Q (Node.js)

$q (Angular)

RSVP.js (Ember)

promise.rb (Ruby)

… many more

CompatibilityIn general, JavaScript promises API will treat anything with a then method as promise-like

Compatibility“anything with a then method” - my tests helper:

@promiseStub = (success, failure) ->

then: (callback) -> callback(success,failure)

Example usage:

spyOn(Api, 'getUser').andReturn promiseStub {id: 1, name: 'Tom'}

CompatibilityAngularJS: angularPromise = $q.when($.ajax('/whatever.json'))

Wraps an object that might be a value or a (3rd party) then-able promise into a $q promise

Source: https://docs.angularjs.org/api/ng/service/$q

AngularJS $q

$q can be used in two fashions● Kowal's Q or jQuery's Deferred● other, similar to ES6 promises

Source: https://docs.angularjs.org/api/ng/service/$q

Summary

● promises make code much cleaner and easier to debug and test

● promises can be:○ chained (each .than modified result for next .than)○ executed in parallel ( $q.all(promisesArray) )○ stored (i.e. for caching)○ passed as argument to function/object/directive/...○ returned from function