Canceling jobs
hwhh opened this issue · 10 comments
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.
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