I'm trying to determine the best way to allow a user to pass a class's method into a promise chain. Currently the code looks like this, and I get the error I expect.
class Parent {
async say(word) {
console.log(word);
}
}
class MyClass extends Parent {
async start() {
console.log("OK, starting");
return "starting";
}
async doThis(something) {
this.say(something);
}
}
async function boot() {
const cl = new MyClass();
await cl.start().then(cl.doThis); <-- Scoping issue
}
boot();
// Output
OK, starting
code.js:16
this.say(something);
^
TypeError: Cannot read properties of undefined (reading 'say')
at doThis (code.js:16:8)
at process.processTicksAndRejections (node:internal/process/task_queues:95:5)
at async boot (code.js:22:2)
I fully expect that error, because (from what I understand) when I pass the cl.doThis
as part of the resolution chain, I'm actually passing in the function itself and this
is getting re-bound. Please correct me if I'm wrong on that assumption, but again I expect that to fail.
My response would be to change to a proper function so the proper binding is kept:
async function boot() {
const cl = new MyClass();
await cl.start().then(response => cl.doThis(response));
}
What I'm being told though it to use super
instead of this
when I'm calling parent functions.
class MyClass extends Parent {
// ...
async doThis(something) {
super.say(something);
}
}
This just avoids the error as we are no longer using this
, it seems very heavy-handed to always call super.<method>()
and end up having to keep track of which methods are being invoked from the parent class (and this is ignoring if one child class overrides a parent one, now I've got some classes invoking super
and others using this
).
Is there a better way to solve this, or is it OK to just say you need to wrap the class method calls in a proper function to keep scope?