Make InteractionManager tasks cancellable
Summary: Returns a promise-like object with a new cancel function that will dig through the queue and remove relevant tasks before they are executed. Handy when tasks are scheduled in react components but should be cleaned up in unmount. Reviewed By: devknoll Differential Revision: D3406953 fbshipit-source-id: edf1157d831d5d6b63f13ee64cfd1c46843e79fa
- Loading branch information
@@ -16,6 +16,7 @@ const EventEmitter = require('EventEmitter'); | ||
const Set = require('Set'); | ||
const TaskQueue = require('TaskQueue'); | ||
|
||
const infoLog = require('infoLog'); | ||
const invariant = require('fbjs/lib/invariant'); | ||
const keyMirror = require('fbjs/lib/keyMirror'); | ||
const setImmediate = require('setImmediate'); | ||
@@ -84,24 +85,33 @@ var InteractionManager = { | ||
}), | ||
|
||
/** | ||
* Schedule a function to run after all interactions have completed. | ||
* Schedule a function to run after all interactions have completed. Returns a cancellable | ||
* "promise". | ||
*/ | ||
runAfterInteractions(task: ?Task): Promise<any> { | ||
return new Promise(resolve => { | ||
runAfterInteractions(task: ?Task): {then: Function, done: Function, cancel: Function} { | ||
const tasks = []; | ||
const promise = new Promise(resolve => { | ||
_scheduleUpdate(); | ||
if (task) { | ||
_taskQueue.enqueue(task); | ||
tasks.push(task); | ||
} | ||
const name = task && task.name || '?'; | ||
_taskQueue.enqueue({run: resolve, name: 'resolve ' + name}); | ||
tasks.push({run: resolve, name: 'resolve ' + (task && task.name || '?')}); | ||
_taskQueue.enqueueTasks(tasks); | ||
}); | ||
return { | ||
then: promise.then.bind(promise), | ||
done: promise.done.bind(promise), | ||
This comment has been minimized.
This comment has been minimized.
roman01la
|
||
cancel: function() { | ||
_taskQueue.cancelTasks(tasks); | ||
}, | ||
}; | ||
}, | ||
|
||
/** | ||
* Notify manager that an interaction has started. | ||
*/ | ||
createInteractionHandle(): Handle { | ||
DEBUG && console.log('create interaction handle'); | ||
DEBUG && infoLog('create interaction handle'); | ||
_scheduleUpdate(); | ||
var handle = ++_inc; | ||
_addInteractionSet.add(handle); | ||
@@ -112,7 +122,7 @@ var InteractionManager = { | ||
* Notify manager that an interaction has completed. | ||
*/ | ||
clearInteractionHandle(handle: Handle) { | ||
DEBUG && console.log('clear interaction handle'); | ||
DEBUG && infoLog('clear interaction handle'); | ||
invariant( | ||
!!handle, | ||
'Must provide a handle to clear.' | ||
5 comments
on commit be09ccc
This comment has been minimized.
This comment has been minimized.
This comment has been minimized.
This comment has been minimized.
This comment has been minimized.
This comment has been minimized.
Oops, yeah, it's possible to cancel the last task and leave _queueStack in an invalid state. Fix coming. |
This comment has been minimized.
This comment has been minimized.
Also, can you guys confirm if this is a bug: #8624 or has the semantic of runAfterInteractions changed to a fire-and-forget? (is there a guarantee it's always called) Thanks |
This comment has been minimized.
This comment has been minimized.
FangHaydn
replied
Dec 6, 2018
I have the same problem. in another component i add a loop animate, but I forgot to stop it. so I add this code:
|
@sahrens
InteractionManager
is broken in my setup. I tracked it down to this line. I don't havedone
in myPromise
prototype. Usingbabel-preset-react-native
, on Android. So my app is broken in 0.29 unless I do thisPromise.prototype.done = () => {}
Willing to send a PR to fix this. What do you suggest I do?