Skip to content

Commit

Permalink
adding asynchronous-safety with the event stack
Browse files Browse the repository at this point in the history
  • Loading branch information
Maurice Fonk committed Apr 3, 2011
1 parent 1e2b342 commit 8253589
Show file tree
Hide file tree
Showing 6 changed files with 80 additions and 12 deletions.
20 changes: 15 additions & 5 deletions coffee/lib/di.coffee
Original file line number Diff line number Diff line change
Expand Up @@ -91,8 +91,12 @@ class Container extends EventEmitter

# We're already waiting on this service to become available...
if @resolving[id]?
@on "resolved.#{id}", (service) -> @handleAsync id, service, diConfig, callback
@on "async.#{id}", (service) ->
callback service
else
# We're resolving now
@resolving[id] = true

# No injection to resolve, that's the easy case :x
return @handleAsync id, (@instantiate required, diConfig), diConfig, callback if not diConfig.inject?

Expand Down Expand Up @@ -143,14 +147,20 @@ class Container extends EventEmitter

# Handle any async actions *after* intanstiation
handleAsync: (id, service, diConfig, parentCallback) ->
# We're no longer resolving
delete @resolving[id]

# Complete the async stuff, time to finally bubble upwards
complete = (service) =>
# Notify others who may be waiting for this service
@emit "async.#{id}", service
delete @resolving[id]

parentCallback service

# No instance calls to do
return parentCallback service if not diConfig.callback?
return complete service if not diConfig.callback?

# Call the callback to retrieve the actual service
diConfig.callback service, (service) -> parentCallback service
diConfig.callback service, (service) -> complete service

# Resolve an id to the relevant type, note it can resolve to undefined
getDiConfig: (id) ->
Expand Down
17 changes: 16 additions & 1 deletion coffee/test/asynchronous-services.coffee
Original file line number Diff line number Diff line change
Expand Up @@ -29,4 +29,19 @@ module.exports = testCase

@dic.get 'withCallback', (service) ->
test.equal service, 'foo'
do test.done
do test.done

'When calling a service with a slow instantiation twice we get the same object': (test) ->
test.expect 1
resolved = null
check = (service) ->
console.log service
if resolved
test.equal service, resolved
do test.done
else
resolved = service

# Fire twice
@dic.get 'withSlowCallback', check
@dic.get 'withSlowCallback', check
13 changes: 12 additions & 1 deletion coffee/test/config/async.coffee
Original file line number Diff line number Diff line change
Expand Up @@ -11,4 +11,15 @@ module.exports =
callback: (async, callback) ->
async.connect (error, someVal) ->
throw "Error!" if error
callback someVal
callback someVal

withSlowCallback:
require: 'test/lib/testAsync'

# Callback on the instance
callback: (async, callback) ->

fn = () -> callback do Math.random
setTimeout fn, 100


16 changes: 11 additions & 5 deletions lib/di.js

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

16 changes: 16 additions & 0 deletions test/asynchronous-services.js
Original file line number Diff line number Diff line change
Expand Up @@ -15,6 +15,22 @@
test.equal(service, 'foo');
return test.done();
});
},
'When calling a service with a slow instantiation twice we get the same object': function(test) {
var check, resolved;
test.expect(1);
resolved = null;
check = function(service) {
console.log(service);
if (resolved) {
test.equal(service, resolved);
return test.done();
} else {
return resolved = service;
}
};
this.dic.get('withSlowCallback', check);
return this.dic.get('withSlowCallback', check);
}
});
}).call(this);
10 changes: 10 additions & 0 deletions test/config/async.js
Original file line number Diff line number Diff line change
Expand Up @@ -10,6 +10,16 @@
return callback(someVal);
});
}
},
withSlowCallback: {
require: 'test/lib/testAsync',
callback: function(async, callback) {
var fn;
fn = function() {
return callback(Math.random());
};
return setTimeout(fn, 100);
}
}
};
}).call(this);

0 comments on commit 8253589

Please sign in to comment.