index.js 1.2 KB

1234567891011121314151617181920212223242526272829303132333435363738394041424344454647484950515253545556575859606162
  1. /*!
  2. * finished
  3. * Copyright(c) 2014 Jonathan Ong
  4. * MIT Licensed
  5. */
  6. /**
  7. * Module dependencies.
  8. */
  9. var first = require('ee-first')
  10. /**
  11. * Variables.
  12. */
  13. /* istanbul ignore next */
  14. var defer = typeof setImmediate === 'function'
  15. ? setImmediate
  16. : function(fn){ process.nextTick(fn.bind.apply(fn, arguments)) }
  17. /**
  18. * Invoke callback when the response has finished, useful for
  19. * cleaning up resources afterwards.
  20. *
  21. * @param {object} thingie
  22. * @param {function} callback
  23. * @return {object}
  24. * @api public
  25. */
  26. module.exports = function finished(thingie, callback) {
  27. var socket = thingie.socket || thingie
  28. var res = thingie.res || thingie
  29. if (res.finished || !socket.writable) {
  30. defer(callback)
  31. return thingie
  32. }
  33. var listener = res.__onFinished
  34. // create a private single listener with queue
  35. if (!listener || !listener.queue) {
  36. listener = res.__onFinished = function onFinished(err) {
  37. if (res.__onFinished === listener) res.__onFinished = null
  38. var queue = listener.queue || []
  39. while (queue.length) queue.shift()(err)
  40. }
  41. listener.queue = []
  42. // finished on first event
  43. first([
  44. [socket, 'error', 'close'],
  45. [res, 'finish'],
  46. ], listener)
  47. }
  48. listener.queue.push(callback)
  49. return thingie
  50. }