| import { AsyncAction } from './AsyncAction'; |
| import { AsyncScheduler } from './AsyncScheduler'; |
| |
| export class AsapScheduler 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; |
| } |
| } |
| } |