|
330 | 330 | * var p = new promise.Promise(function(fulfill) {
|
331 | 331 | * setTimeout(fulfill, 100);
|
332 | 332 | * });
|
333 |
| - * |
334 | 333 | * p.then(() => console.log('promise resolved!'));
|
335 |
| - * |
| 334 | + * flow.execute(() => console.log('sub-task!')); |
336 | 335 | * }).then(function() {
|
337 | 336 | * console.log('task complete!');
|
338 | 337 | * });
|
| 338 | + * // sub-task! |
339 | 339 | * // task complete!
|
340 | 340 | * // promise resolved!
|
341 | 341 | *
|
@@ -1296,7 +1296,7 @@ promise.Promise = goog.defineClass(null, {
|
1296 | 1296 | this.callbacks_ = [];
|
1297 | 1297 | }
|
1298 | 1298 | this.callbacks_.push(cb);
|
1299 |
| - cb.isVolatile = true; |
| 1299 | + cb.blocked = true; |
1300 | 1300 | this.flow_.getActiveQueue_().enqueue(cb);
|
1301 | 1301 | }
|
1302 | 1302 |
|
@@ -2491,12 +2491,20 @@ var Task = goog.defineClass(promise.Deferred, {
|
2491 | 2491 | this.queue = null;
|
2492 | 2492 |
|
2493 | 2493 | /**
|
2494 |
| - * Whether this task is volatile. Volatile tasks may be registered in a |
2495 |
| - * a task queue, but will be dropped on the next turn of the JS event loop |
2496 |
| - * if still marked volatile. |
| 2494 | + * Whether this task is considered block. A blocked task may be registered |
| 2495 | + * in a task queue, but will be dropped if it is still blocked when it |
| 2496 | + * reaches the front of the queue. A dropped task may always be rescheduled. |
| 2497 | + * |
| 2498 | + * Blocked tasks are used when a callback is attached to an unsettled |
| 2499 | + * promise to reserve a spot in line (in a manner of speaking). If the |
| 2500 | + * promise is not settled before the callback reaches the front of the |
| 2501 | + * of the queue, it will be dropped. Once the promise is settled, the |
| 2502 | + * dropped task will be rescheduled as an interrupt on the currently task |
| 2503 | + * queue. |
| 2504 | + * |
2497 | 2505 | * @type {boolean}
|
2498 | 2506 | */
|
2499 |
| - this.isVolatile = false; |
| 2507 | + this.blocked = false; |
2500 | 2508 |
|
2501 | 2509 | if (opt_stackOptions) {
|
2502 | 2510 | this.promise.stack_ = promise.captureStackTrace(
|
@@ -2537,9 +2545,6 @@ var TaskQueue = goog.defineClass(EventEmitter, {
|
2537 | 2545 | /** @private {!Array<!Task>} */
|
2538 | 2546 | this.tasks_ = [];
|
2539 | 2547 |
|
2540 |
| - /** @private {Array<!Task>} */ |
2541 |
| - this.volatileTasks_ = null; |
2542 |
| - |
2543 | 2548 | /** @private {Array<!Task>} */
|
2544 | 2549 | this.interrupts_ = null;
|
2545 | 2550 |
|
@@ -2592,11 +2597,6 @@ var TaskQueue = goog.defineClass(EventEmitter, {
|
2592 | 2597 | throw Error('Task is already scheduled in another queue');
|
2593 | 2598 | }
|
2594 | 2599 |
|
2595 |
| - if (task.isVolatile) { |
2596 |
| - this.volatileTasks_ = this.volatileTasks_ || []; |
2597 |
| - this.volatileTasks_.push(task); |
2598 |
| - } |
2599 |
| - |
2600 | 2600 | this.tasks_.push(task);
|
2601 | 2601 | task.queue = this;
|
2602 | 2602 | task.promise[CANCEL_HANDLER_SYMBOL] =
|
@@ -2628,10 +2628,9 @@ var TaskQueue = goog.defineClass(EventEmitter, {
|
2628 | 2628 | return;
|
2629 | 2629 | }
|
2630 | 2630 | promise.callbacks_.forEach(function(cb) {
|
2631 |
| - cb.promise[CANCEL_HANDLER_SYMBOL] = |
2632 |
| - this.onTaskCancelled_.bind(this, cb); |
| 2631 | + cb.promise[CANCEL_HANDLER_SYMBOL] = this.onTaskCancelled_.bind(this, cb); |
2633 | 2632 |
|
2634 |
| - cb.isVolatile = false; |
| 2633 | + cb.blocked = false; |
2635 | 2634 | if (cb.queue === this && this.tasks_.indexOf(cb) !== -1) {
|
2636 | 2635 | return;
|
2637 | 2636 | }
|
@@ -2711,7 +2710,6 @@ var TaskQueue = goog.defineClass(EventEmitter, {
|
2711 | 2710 | return;
|
2712 | 2711 | }
|
2713 | 2712 | this.state_ = TaskQueueState.STARTED;
|
2714 |
| - this.dropVolatileTasks_(); |
2715 | 2713 |
|
2716 | 2714 | if (this.pending_ != null || this.processUnhandledRejections_()) {
|
2717 | 2715 | return;
|
@@ -2762,7 +2760,6 @@ var TaskQueue = goog.defineClass(EventEmitter, {
|
2762 | 2760 | return fn();
|
2763 | 2761 | } finally {
|
2764 | 2762 | this.flow_.activeQueue_ = null;
|
2765 |
| - this.dropVolatileTasks_(); |
2766 | 2763 | activeFlows.pop();
|
2767 | 2764 | }
|
2768 | 2765 | },
|
@@ -2801,23 +2798,6 @@ var TaskQueue = goog.defineClass(EventEmitter, {
|
2801 | 2798 | }
|
2802 | 2799 | },
|
2803 | 2800 |
|
2804 |
| - /** |
2805 |
| - * Drops any volatile tasks scheduled within this task queue. |
2806 |
| - * @private |
2807 |
| - */ |
2808 |
| - dropVolatileTasks_: function() { |
2809 |
| - if (!this.volatileTasks_) { |
2810 |
| - return; |
2811 |
| - } |
2812 |
| - for (var task of this.volatileTasks_) { |
2813 |
| - if (task.isVolatile) { |
2814 |
| - vlog(2, () => this + ' dropping volatile task ' + task, this); |
2815 |
| - this.dropTask_(task); |
2816 |
| - } |
2817 |
| - } |
2818 |
| - this.volatileTasks_ = null; |
2819 |
| - }, |
2820 |
| - |
2821 | 2801 | /**
|
2822 | 2802 | * @param {!Task} task The task to drop.
|
2823 | 2803 | * @private
|
@@ -2882,13 +2862,21 @@ var TaskQueue = goog.defineClass(EventEmitter, {
|
2882 | 2862 | */
|
2883 | 2863 | getNextTask_: function() {
|
2884 | 2864 | var task = undefined;
|
2885 |
| - if (this.interrupts_) { |
2886 |
| - task = this.interrupts_.shift(); |
2887 |
| - } |
2888 |
| - if (!task && this.tasks_) { |
2889 |
| - task = this.tasks_.shift(); |
| 2865 | + while (true) { |
| 2866 | + if (this.interrupts_) { |
| 2867 | + task = this.interrupts_.shift(); |
| 2868 | + } |
| 2869 | + if (!task && this.tasks_) { |
| 2870 | + task = this.tasks_.shift(); |
| 2871 | + } |
| 2872 | + if (task && task.blocked) { |
| 2873 | + vlog(2, () => this + ' skipping blocked task ' + task, this); |
| 2874 | + task.queue = null; |
| 2875 | + task = null; |
| 2876 | + continue; |
| 2877 | + } |
| 2878 | + return task; |
2890 | 2879 | }
|
2891 |
| - return task; |
2892 | 2880 | }
|
2893 | 2881 | });
|
2894 | 2882 |
|
|
0 commit comments