SimonErm / react-native-job-queue

Easy to use react-native queuing library
https://simonerm.github.io/react-native-job-queue/
122 stars 33 forks source link

Canceling jobs #19

Closed hwhh closed 3 years ago

hwhh commented 4 years ago

Question

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

hannojg commented 4 years ago

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

hwhh commented 4 years ago

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 ?

hannojg commented 4 years ago

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.

SimonErm commented 4 years ago

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.

myckhel commented 3 years ago

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),
    }
  )
}
SimonErm commented 3 years ago

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

myckhel commented 3 years ago

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?

SimonErm commented 3 years ago

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

myckhel commented 3 years ago

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

SimonErm commented 3 years ago

Implemented by https://github.com/SimonErm/react-native-job-queue/pull/39