I am looking to implement the ability to cancel a running promise in my Vue component, specifically a promise returned by a Vuex action.
In my scenario, the Vuex action is continuously polling an endpoint for status updates, and I need the capability to stop this polling when a certain user action (such as closing a function) occurs.
Although I have created a custom CancellablePromise class inspired by a solution from Stack Overflow, it does not seem to work seamlessly with Vuex.
Cancellable promise class (from )
export class CancellablePromise<T> extends Promise<T> {
private onCancel: () => void;
constructor(
executor: (
resolve: (value?: T | PromiseLike<T>) => void,
reject: (reason?: any) => void,
onCancel: (cancelHandler: () => void) => void
) => void
) {
let onCancel: () => void;
super((rs, rj) =>
executor(rs, rj, (ch: () => void) => {
onCancel = ch;
})
);
this.onCancel = onCancel;
}
public cancel(): void {
if (this.onCancel) {
this.onCancel();
}
}
}
Action
async [SomeAction.foo]({ state, dispatch, commit, rootGetters }) {
const cancellablePromise = new CancellablePromise<any>((resolve, reject, onCancel) => {
const interval = setInterval(async () => {
const status = await dispatch(SomeAction.bar);
if (status === "goodstatus") {
clearInterval(interval);
resolve();
} else if (status === "badstatus") {
clearInterval(interval);
reject();
}
}, 2000);
onCancel(() => {
clearInterval(interval);
reject();
});
});
return cancellablePromise;
}
Component
data: (() => {
promise: undefined as CancellablePromise<any> | undefined
}),
async call() {
this.promise = this.$store
.dispatch(SomeAction.foo)
.then(response => {
// do something
}) as CancellablePromise<any>;
},
close(): void {
if (this.promise) {
this.promise.cancel(); // outputs cancel is not a function
}
}
An issue arises in the close
function where this.promise.cancel
throws an error stating that cancel is not a function.
This appears to be because the object returned by dispatch
is indeed a Promise rather than a CancellablePromise. My suspicion stems from examining the Vuex source code, which suggests that a new Promise is created from the Promise returned by the action. While I may not be well-versed in TypeScript's type system, it seems like my CancellablePromise
is somehow not being utilized correctly here.
How can I achieve my intended functionality in this situation?