The LM Control website. Simple yet efficient.
Vous ne pouvez pas sélectionner plus de 25 sujets Les noms de sujets doivent commencer par une lettre ou un nombre, peuvent contenir des tirets ('-') et peuvent comporter jusqu'à 35 caractères.

index.js 3.6KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196
  1. /*!
  2. * on-finished
  3. * Copyright(c) 2013 Jonathan Ong
  4. * Copyright(c) 2014 Douglas Christopher Wilson
  5. * MIT Licensed
  6. */
  7. 'use strict'
  8. /**
  9. * Module exports.
  10. * @public
  11. */
  12. module.exports = onFinished
  13. module.exports.isFinished = isFinished
  14. /**
  15. * Module dependencies.
  16. * @private
  17. */
  18. var first = require('ee-first')
  19. /**
  20. * Variables.
  21. * @private
  22. */
  23. /* istanbul ignore next */
  24. var defer = typeof setImmediate === 'function'
  25. ? setImmediate
  26. : function(fn){ process.nextTick(fn.bind.apply(fn, arguments)) }
  27. /**
  28. * Invoke callback when the response has finished, useful for
  29. * cleaning up resources afterwards.
  30. *
  31. * @param {object} msg
  32. * @param {function} listener
  33. * @return {object}
  34. * @public
  35. */
  36. function onFinished(msg, listener) {
  37. if (isFinished(msg) !== false) {
  38. defer(listener, null, msg)
  39. return msg
  40. }
  41. // attach the listener to the message
  42. attachListener(msg, listener)
  43. return msg
  44. }
  45. /**
  46. * Determine if message is already finished.
  47. *
  48. * @param {object} msg
  49. * @return {boolean}
  50. * @public
  51. */
  52. function isFinished(msg) {
  53. var socket = msg.socket
  54. if (typeof msg.finished === 'boolean') {
  55. // OutgoingMessage
  56. return Boolean(msg.finished || (socket && !socket.writable))
  57. }
  58. if (typeof msg.complete === 'boolean') {
  59. // IncomingMessage
  60. return Boolean(msg.upgrade || !socket || !socket.readable || (msg.complete && !msg.readable))
  61. }
  62. // don't know
  63. return undefined
  64. }
  65. /**
  66. * Attach a finished listener to the message.
  67. *
  68. * @param {object} msg
  69. * @param {function} callback
  70. * @private
  71. */
  72. function attachFinishedListener(msg, callback) {
  73. var eeMsg
  74. var eeSocket
  75. var finished = false
  76. function onFinish(error) {
  77. eeMsg.cancel()
  78. eeSocket.cancel()
  79. finished = true
  80. callback(error)
  81. }
  82. // finished on first message event
  83. eeMsg = eeSocket = first([[msg, 'end', 'finish']], onFinish)
  84. function onSocket(socket) {
  85. // remove listener
  86. msg.removeListener('socket', onSocket)
  87. if (finished) return
  88. if (eeMsg !== eeSocket) return
  89. // finished on first socket event
  90. eeSocket = first([[socket, 'error', 'close']], onFinish)
  91. }
  92. if (msg.socket) {
  93. // socket already assigned
  94. onSocket(msg.socket)
  95. return
  96. }
  97. // wait for socket to be assigned
  98. msg.on('socket', onSocket)
  99. if (msg.socket === undefined) {
  100. // node.js 0.8 patch
  101. patchAssignSocket(msg, onSocket)
  102. }
  103. }
  104. /**
  105. * Attach the listener to the message.
  106. *
  107. * @param {object} msg
  108. * @return {function}
  109. * @private
  110. */
  111. function attachListener(msg, listener) {
  112. var attached = msg.__onFinished
  113. // create a private single listener with queue
  114. if (!attached || !attached.queue) {
  115. attached = msg.__onFinished = createListener(msg)
  116. attachFinishedListener(msg, attached)
  117. }
  118. attached.queue.push(listener)
  119. }
  120. /**
  121. * Create listener on message.
  122. *
  123. * @param {object} msg
  124. * @return {function}
  125. * @private
  126. */
  127. function createListener(msg) {
  128. function listener(err) {
  129. if (msg.__onFinished === listener) msg.__onFinished = null
  130. if (!listener.queue) return
  131. var queue = listener.queue
  132. listener.queue = null
  133. for (var i = 0; i < queue.length; i++) {
  134. queue[i](err, msg)
  135. }
  136. }
  137. listener.queue = []
  138. return listener
  139. }
  140. /**
  141. * Patch ServerResponse.prototype.assignSocket for node.js 0.8.
  142. *
  143. * @param {ServerResponse} res
  144. * @param {function} callback
  145. * @private
  146. */
  147. function patchAssignSocket(res, callback) {
  148. var assignSocket = res.assignSocket
  149. if (typeof assignSocket !== 'function') return
  150. // res.on('socket', callback) is broken in 0.8
  151. res.assignSocket = function _assignSocket(socket) {
  152. assignSocket.call(this, socket)
  153. callback(socket)
  154. }
  155. }