74 lines
1.7 KiB
JavaScript
74 lines
1.7 KiB
JavaScript
/**
|
|
* Call callback when request finished. Lifted off of
|
|
* npm on-finished with slight optimizations.
|
|
*/
|
|
|
|
module.exports = function onFinished(msg, callback) {
|
|
let alreadyFinished = false;
|
|
|
|
// Make sure it hasn't finished already.
|
|
// Although I highly doubt this code is necessary.
|
|
if (typeof msg.finished === 'boolean') {
|
|
alreadyFinished = msg.finished || (msg.socket && !msg.socket.writable);
|
|
} else if (typeof msg.complete === 'boolean') {
|
|
alreadyFinished = msg.upgrade || !msg.socket || !msg.socket.readable || (msg.complete && !msg.readable);
|
|
} else {
|
|
// We don't support this object so end immediately
|
|
alreadyFinished = true;
|
|
}
|
|
|
|
if (alreadyFinished) {
|
|
return setImmediate(callback, null, msg);
|
|
}
|
|
|
|
if (msg.__onFinished) {
|
|
return msg.__onFinished.push(callback);
|
|
}
|
|
msg.__onFinished = [callback];
|
|
|
|
let socket = null;
|
|
let finished = false;
|
|
|
|
function onFinish(error) {
|
|
if (finished) return;
|
|
|
|
msg.removeListener('end', onFinish);
|
|
msg.removeListener('finish', onFinish);
|
|
|
|
if (socket) {
|
|
socket.removeListener('error', onFinish);
|
|
socket.removeListener('close', onFinish);
|
|
}
|
|
|
|
socket = null;
|
|
finished = true;
|
|
|
|
msg.__onFinished.forEach(cb => cb(error, msg));
|
|
}
|
|
|
|
msg.on('end', onFinish);
|
|
msg.on('finish', onFinish);
|
|
|
|
function onSocket(newSocket) {
|
|
// remove listener
|
|
msg.removeListener('socket', onSocket);
|
|
|
|
if (finished) return;
|
|
if (socket) return;
|
|
|
|
socket = newSocket;
|
|
|
|
// finished on first socket event
|
|
socket.on('error', onFinish);
|
|
socket.on('close', onFinish);
|
|
}
|
|
|
|
if (msg.socket) {
|
|
// socket already assigned
|
|
onSocket(msg.socket);
|
|
return;
|
|
}
|
|
|
|
// wait for socket to be assigned
|
|
msg.on('socket', onSocket);
|
|
};
|