-
Notifications
You must be signed in to change notification settings - Fork 2
Expand file tree
/
Copy pathcontainer.coffee
More file actions
89 lines (72 loc) · 1.88 KB
/
container.coffee
File metadata and controls
89 lines (72 loc) · 1.88 KB
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
{defer} = require 'node-promise'
promise = (f) ->
deferred = defer()
result = f deferred.resolve, deferred.reject
deferred.promise
###
Given a list of promises, creates a promise that will be resolved or rejected
when all the promises on the list have either been resolved or rejected. In
case of mixed successes the result will be a rejection.
###
all = (promises) -> promise (resolve, reject) ->
resolve() if promises.length is 0
resolved = []
rejected = []
next = ->
return unless resolved.length + rejected.length == promises.length
if rejected.length is 0
resolve resolved
else
reject rejected
for p in promises
p.then (value) ->
resolved.push value
do next
, (error) ->
rejected.push error
do next
multimethod = (single, multiple) -> ->
if arguments.length is 1
single.apply this, arguments
else
multiple.call this, arguments
class Resolver
resources: null
busy: null
constructor: (@resources = {}, @busy = []) ->
has: multimethod(
(name) ->
@resources[name]?
(names) ->
return true for name in names when @has name
return false
)
get: multimethod(
(name) ->
unless @has name
throw new Error("Resource '#{name}' not available")
scope = @using name
promise (resolve, reject) =>
@resources[name].call scope, resolve, reject, scope
(names) ->
promises = (@get name for name in names)
all promises
)
using: (name) ->
if name in @busy
throw new Error("Recursive definition of resource '#{name}' detected")
new Resolver @resources, [@busy..., name]
module.exports = class Container
resources: null
constructor: (@resources = {}) ->
resolver: -> new Resolver(@resources)
describe: (name, descriptor) ->
@resources[name] = descriptor
this
set: (name, value) ->
@describe name, (result, error) ->
result value
has: (name) ->
@resources[name]?
get: ->
@resolver().get arguments...