I'm creating a subclass of the NodeJS http.Agent
to get rid of the queuing behavior when it has reached the socket limit. I've overridden addRequest
to track the number of concurrent requests per target, rejecting requests when no capacity is available to handle it.
The issue is that I also need to extend https.Agent
, which is itself a subclass of http.Agent
, with the same behavior. If I create an addRequest
function and assign it to the prototype of my subclasses of each agent, I'm unable to reference super
. Is there a reasonably DRY way to do this?
The following code is excessively simple, but hopefully illustrates the problem.
class Original {
addRequest(req) {
console.log(req);
}
/* other stuff */
}
class ExtendedOriginal extends Original {
/* various extensions of other stuff */
}
/* Custom */
class ConcurrencyLimitedOriginal extends Original {
addRequest(req) {
if (this.canAddRequest(req)) {
super.addRequest(req); // super ref! Can only exist as a method, not a function
}
canAddRequest(req) {
/* various logic */
return true;
}
}
class ConcurrencyLimitedExtendedOriginal extends ExtendedOriginal {
/* DRY way to have same added logic as ConcurrencyLimitedOriginal? */
}
I solved this without mixins, due to issues with getting that approach to work discussed in comments. Instead, I took advantage of Class Expressions to instead more easily define two different subclasses with separate parentage but otherwise identical implementations:
const createConcurrencyLimitedAgentClass = (parentAgent) =>
class extends parentAgent {
constructor(options) {
super(options);
// other init logic
}
// other method overrides
};
const ConcurrencyLimitedHttpAgent = createConcurrencyLimitedAgentClass(Agent);
const ConcurrencyLimitedHttpsAgent = createConcurrencyLimitedAgentClass(HttpsAgent);
I'm not sure I'd call it the cleanest looking code ever, but I'm not convinced that there is a clean way to solve this given the existing class structure. Resulting structure from this approach looks like the following:
http.Agent
| |
| https.Agent
| |
| ConcurrencyLimitedHttpsAgent
|
ConcurrencyLimitedHttpAgent
The two concurrency limiting agents are identical in implementation except they reference a different super
.