SimonErm/react-native-job-queue

Canceling jobs

hwhh opened this issue · 10 comments

hwhh commented

Question

Is it possible to cancel a job after it's been added but before it's been executed?

I was just going through the code base: no you can't, this has to be implemented.

hwhh commented

Would this be as simple as calling removeJob; I saw this is implemented as:

removeJob(rawJob: RawJob): void {
       this.jobs = this.jobs.filter((job) => job.id !== rawJob.id);
}

But it seems like this only removed the job from the JobStore, but doesn't actually cancel it - is that correct and if so do you know what would have to be done in order to cancel the job ?

Ah, so removeJob is a public method available to us on the JobStore? This should be fine, because the job store is where it takes unexecuted jobs from. This means it will only work to remove the job if it hasn't executed yet. If you call this while the job executes it won't get canceled.

That's right @hannojg . I am not sure if i'ts possible to implement canceling an already runnig job since the promise has to be aborted this way.

currently implementing the ability to cancel running job on this branch https://github.com/myckhel/react-native-job-queue/tree/ft-job_cancel

usage example:

import queue, {Worker, CANCEL} from 'react-native-job-queue';

export const jobDemo = () => {
  return new Worker(
    'demo', (payload) => {
      let cancel
      const promise = new Promise(function(resolve, reject) {
        const timeout = setTimeout(() => {
          console.log('through');
          resolve()
        }, 5000)

        cancel = () => {
          console.log('canceled', timeout);
          clearTimeout(timeout)
          console.log('timeout', timeout);
          reject({message: 'canceleds'})
        }
      });
      promise[CANCEL] = cancel
      console.log('assing', promise);
      return promise
    },
    {
      onFailure: (p) => console.log('failed', p),
      onCompletion: (p) => console.log('complete', p),
      onSuccess: (p) => console.log('success', p),
      onStart: (p) => console.log('onStart', p.id),
    }
  )
}

Nice to see that you are working on this, but currently it's not possible to cancel plain js promise: https://stackoverflow.com/questions/30233302/promise-is-it-possible-to-force-cancel-a-promise

Well promises cannot be cancelled but you can reject a promise and stop the promise tasks manually.

Almost same approach as the answer from the stackoverflow thread.

The promise has to implement a cancel method

For example

Assuming you created a job that will run for 5 secs

const job = () => new Promise((resolve, reject) => {
setTimeout(() => {
          console.log('job done after 5 sec');
          resolve()
        }, 5000)
})
job() // Promise{}
// job done after 5 sec

But you would like to cancel the job sometimes before finishing
Then the job needs to have a cancel method
So that we can cancel the job

const job = () => {
// initialize a global var
let cancel;
const promise = new Promise((resolve, reject) => {
// keep track of the timeout ref
const timeout = setTimeout(() => {
          console.log('job done after 5 sec');
          resolve()
        }, 5000)

// set global cancel var a function 
cancel = () => {
    // manually stop the task this promise running 
    clearTimeout(timeout)
    // reject the promise to throw cancelled error
    reject({message: 'cancelled'})
}
})
// give the promise the implemented cancel method
promise.cancel = cancel
// return the modified promise
return promise
}

// Keep track of the job returned promise
const jobPromise = job() // Promise{cancel: function}

// cancel the job after 3 secs
setTimeout(() => jobPromise.cancel(), 3000)
// nothing was logged because the job was cancelled after 3 secs

Now did you see that promises can be cancelled if only the user provides a cancel method?

Yes and that sounds good 👍 I think this would be a great improvement for this lib. :-)

Already implemented the cancel feature.
I will read about react-native-blob tomorrow so i can build the package

Implemented by #39