select.js 1.3 KB

1234567891011121314151617181920212223242526272829303132333435363738394041424344454647484950515253545556
  1. /**
  2. * Module dependencies.
  3. */
  4. var make = require('./make')
  5. var Channel = require('./channel')
  6. /**
  7. * Expose `select`.
  8. */
  9. module.exports = select
  10. /**
  11. * Return the first of the given channels with a value.
  12. *
  13. * @param {Function} channels...
  14. * @return {Function}
  15. * @api public
  16. */
  17. function select(/*channels...*/) {
  18. var selectCh = make(arguments.length)
  19. var chans = [].slice.call(arguments, 0)
  20. // get all channels with values waiting
  21. var full = chans.filter(function (ch) {
  22. return ch.__chan.items.length + ch.__chan.pendingAdds.length > 0
  23. })
  24. // define get callback
  25. var get = function (err, value) {
  26. var args = arguments
  27. var ch = Channel.lastCalled
  28. // remove get callback from all selected channels
  29. chans.forEach(function (ch) { ch.__chan.removeGet(get) })
  30. // add temporary selected yieldable function
  31. ch.selected = function (cb) {
  32. delete ch.selected
  33. cb.apply(null, args)
  34. }
  35. // added the selected channel to the select channel
  36. selectCh(null, ch)
  37. selectCh.close()
  38. }
  39. if (full.length > 1) {
  40. // multiple channels with waiting values, pick one at random
  41. full[Math.floor(Math.random() * full.length)](get)
  42. } else {
  43. // add get callback to all channels
  44. chans.forEach(function (ch) { ch(get) })
  45. }
  46. return selectCh
  47. }