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