alkemics/CancelablePromise

Returned promise is not canceled

Closed this issue · 5 comments

There 1500 ms to run and promise3 must be canceled, but it is not.

Timeline:
0 ms: create promise
1000 ms: promise2 was created and finished, than create its children promise3
1500 ms: cancel promise2
2000 ms: promise3 was finished, but it shouldn't have happened

const {CancelablePromise} = require("cancelable-promise");

const promise = new CancelablePromise((resolve, reject, onCancel) => {
  const timer = setTimeout(() => {
    console.log("promise 1 was finished");
    resolve(); 
  }, 1000);
  const abort = () => {
    clearTimeout(timer);
  };
  onCancel(abort);
});

const promise2 = promise.then(() => {
  const promise3 = new CancelablePromise((resolve, reject, onCancel) => {
    const timer = setTimeout(() => {
      console.log("promise 3 was finished");
      resolve(); 
    }, 1000);
    const abort = () => {
      clearTimeout(timer);
    };
    onCancel(abort);
  });
  return promise3;
});

setTimeout(() => {
  promise2.cancel();
}, 1500);

Hi @Filyus, thanks for your feedback. Indeed the lib doesn't handle cancelable promises returned in a then callback. I'll have a look at this 🤓

Yet more complex example with .then after child promise.
To fix this you must call something like childPromise.cancel(); to cancel all of the child chain.

const {CancelablePromise} = require("cancelable-promise");

const promise = new CancelablePromise((resolve, reject, onCancel) => {
  const timer = setTimeout(() => {
    console.log("promise 1 was finished");
    resolve(); 
  }, 1000);
  const abort = () => {
    clearTimeout(timer);
  };
  onCancel(abort);
});

const promise2 = promise.then(() => {
  const promise3 = new CancelablePromise((resolve, reject, onCancel) => {
    const timer = setTimeout(() => {
      console.log("promise 3 was finished");
      resolve(); 
    }, 1000);
    const abort = () => {
      clearTimeout(timer);
    };
    onCancel(abort);
  }).then(() => {
    const promise4 = new CancelablePromise((resolve, reject, onCancel) => {
      const timer = setTimeout(() => {
        console.log("promise 4 was finished");
        resolve(); 
      }, 1000);
      const abort = () => {
        clearTimeout(timer);
      };
      onCancel(abort);
    });
    return promise4;
  });
  return promise3;
});

// setTimeout(() => {
//   promise2.cancel();
// }, 1500);

setTimeout(() => {
  promise2.cancel();
}, 2500);

Yes thank you 👍 the fix I made should handle this case too:

With setTimeout(() => promise2.cancel(), 2500); output will be:

promise 1 was finished
promise 3 was finished

With setTimeout(() => promise2.cancel(), 1500); output will be:

promise 1 was finished

I will probably publish it tomorrow.

@Filyus now it should work as you expect, can you try cancelable-promise@4.1.0?

@alk-sdavid, yes, everything works as it should, thanks!