select.js
1.3 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
/**
* Module dependencies.
*/
var make = require('./make')
var Channel = require('./channel')
/**
* Expose `select`.
*/
module.exports = select
/**
* Return the first of the given channels with a value.
*
* @param {Function} channels...
* @return {Function}
* @api public
*/
function select(/*channels...*/) {
var selectCh = make(arguments.length)
var chans = [].slice.call(arguments, 0)
// get all channels with values waiting
var full = chans.filter(function (ch) {
return ch.__chan.items.length + ch.__chan.pendingAdds.length > 0
})
// define get callback
var get = function (err, value) {
var args = arguments
var ch = Channel.lastCalled
// remove get callback from all selected channels
chans.forEach(function (ch) { ch.__chan.removeGet(get) })
// add temporary selected yieldable function
ch.selected = function (cb) {
delete ch.selected
cb.apply(null, args)
}
// added the selected channel to the select channel
selectCh(null, ch)
selectCh.close()
}
if (full.length > 1) {
// multiple channels with waiting values, pick one at random
full[Math.floor(Math.random() * full.length)](get)
} else {
// add get callback to all channels
chans.forEach(function (ch) { ch(get) })
}
return selectCh
}