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