I have a collection of methods (some synchronous and some asynchronous) that I wish to process sequentially using bluebird.each
. Here's a simplified example:
import bluebird from 'bluebird';
const delay = (ms: number) => new Promise((resolve) => setTimeout(resolve, ms));
class Template {
propertyA!: number;
propertyB!: number;
constructor() {}
async methodA() {
this.propertyA = 10;
console.log({ thisArgInA: this, propertyA: this.propertyA });
await delay(500);
return this.propertyA;
}
methodB() {
this.propertyB = this.propertyA * 100;
console.log({ thisArgInB: this, propertyB: this.propertyB });
return this.propertyB;
}
}
const instance = new Template();
const sequence = [instance.methodA, instance.methodB];
(async function main() {
await bluebird.each(sequence, (fn) => {
const result = fn.call(instance);
console.log({ result });
});
})();
An error is being thrown which I find puzzling:
index.ts:27:20 - error TS2684: The 'this' context of type '(() => Promise<number>) | (() => number)' is not assignable to method's 'this' of type '(this: Template) => Promise<number>'.
Type '() => number' is not assignable to type '(this: Template) => Promise<number>'.
Type 'number' is not assignable to type 'Promise<number>'.
27 const result = fn.call(instance);
I speculated whether the issue arose because bluebird.each
accepts either values or promises that resolve to values causing confusion for the compiler. My attempt at resolving this was to enforce strong typing on the return values"
async methodA: Promise<number> { /*...*/ }
methodB: number { /*...*/ }
However, this did not yield any changes. Additionally, observations include:
- The need for explicit context since executing the functions within the
each
callbacks severs their connection with theTemplate
object asthis
. - When
methodA
operates synchronously (removing theasync
keyword, eliminating thedelay()
, and directly returningthis.propertyA
), all is well. - Removing the
return
statements also resolves issues. - Switching from
fn.call(instance)
tofn.bind(instance)()
restores functionality.
How can I conform to the compiler's expectations so it correctly handles calling these functions in the specified context?
Is there a simpler way to execute these methods sequentially while preserving their link to this
?