Skip to content

Instantly share code, notes, and snippets.

@richthegeek
Last active December 25, 2015 19:08
Show Gist options
  • Save richthegeek/7025163 to your computer and use it in GitHub Desktop.
Save richthegeek/7025163 to your computer and use it in GitHub Desktop.
Allow lazy evaluation of a string, such that you can have asynchronous parts to an otherwise synchronous evaluation. For example, part of the object may need to be loaded from the database but you don't want the code to be written with callbacks.
Q = require 'q'
class DeferredObject
constructor: (data) ->
@data = data
for k, v of @data
@__defineGetter__ k, -> this.data[k]
defer: (key, getter) ->
@__defineGetter__ key, =>
if @data[key]
return @data[key]
defer = Q.defer()
getter @data, (err, result) =>
if err
return defer.resolve [err]
@data[key] = result
defer.resolve [null, result]
throw defer.promise
get: (key, callback) ->
@eval "this.#{key}", callback
eval: (str, callback) ->
try
callback null, eval str
catch err
err.then ?= -> callback err
err.then (arg) =>
[err, result] = arg
if err
return callback err
@eval str, callback
obj = new DeferredObject {foo: 42}
obj.defer 'thing', (data, callback) ->
setTimeout (() -> callback null, 'this is a thing'), 500
obj.eval 'this.thing.length', () ->
console.log 'result', arguments
@richthegeek
Copy link
Author

If a key is already defined in the deferred object, the getter will never be called in a deferred manner.

To defer an existing key, first delete it.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment