f13b51dce76f501aa9a4a2b3ae2ab5229ba82d080ad4ce404364d1cf2b2a9cb47549c3b09e5d9d9508a7165e8081d7428629dabca33fd1ff50c7e7539319ff 1.4 KB

12345678910111213141516171819202122232425262728293031323334353637383940414243
  1. import { AsyncAction } from './AsyncAction';
  2. import { AsyncScheduler } from './AsyncScheduler';
  3. export class AnimationFrameScheduler extends AsyncScheduler {
  4. public flush(action?: AsyncAction<any>): void {
  5. this._active = true;
  6. // The async id that effects a call to flush is stored in _scheduled.
  7. // Before executing an action, it's necessary to check the action's async
  8. // id to determine whether it's supposed to be executed in the current
  9. // flush.
  10. // Previous implementations of this method used a count to determine this,
  11. // but that was unsound, as actions that are unsubscribed - i.e. cancelled -
  12. // are removed from the actions array and that can shift actions that are
  13. // scheduled to be executed in a subsequent flush into positions at which
  14. // they are executed within the current flush.
  15. let flushId;
  16. if (action) {
  17. flushId = action.id;
  18. } else {
  19. flushId = this._scheduled;
  20. this._scheduled = undefined;
  21. }
  22. const { actions } = this;
  23. let error: any;
  24. action = action || actions.shift()!;
  25. do {
  26. if ((error = action.execute(action.state, action.delay))) {
  27. break;
  28. }
  29. } while ((action = actions[0]) && action.id === flushId && actions.shift());
  30. this._active = false;
  31. if (error) {
  32. while ((action = actions[0]) && action.id === flushId && actions.shift()) {
  33. action.unsubscribe();
  34. }
  35. throw error;
  36. }
  37. }
  38. }