Book a Demo!
CoCalc Logo Icon
StoreFeaturesDocsShareSupportNewsAboutPoliciesSign UpSign In
seleniumhq
GitHub Repository: seleniumhq/selenium
Path: blob/trunk/third_party/closure/goog/async/conditionaldelay.js
2868 views
1
// Copyright 2008 The Closure Library Authors. All Rights Reserved.
2
//
3
// Licensed under the Apache License, Version 2.0 (the "License");
4
// you may not use this file except in compliance with the License.
5
// You may obtain a copy of the License at
6
//
7
// http://www.apache.org/licenses/LICENSE-2.0
8
//
9
// Unless required by applicable law or agreed to in writing, software
10
// distributed under the License is distributed on an "AS-IS" BASIS,
11
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
12
// See the License for the specific language governing permissions and
13
// limitations under the License.
14
15
/**
16
* @fileoverview Defines a class useful for handling functions that must be
17
* invoked later when some condition holds. Examples include deferred function
18
* calls that return a boolean flag whether it succedeed or not.
19
*
20
* Example:
21
*
22
* function deferred() {
23
* var succeeded = false;
24
* // ... custom code
25
* return succeeded;
26
* }
27
*
28
* var deferredCall = new goog.async.ConditionalDelay(deferred);
29
* deferredCall.onSuccess = function() {
30
* alert('Success: The deferred function has been successfully executed.');
31
* }
32
* deferredCall.onFailure = function() {
33
* alert('Failure: Time limit exceeded.');
34
* }
35
*
36
* // Call the deferred() every 100 msec until it returns true,
37
* // or 5 seconds pass.
38
* deferredCall.start(100, 5000);
39
*
40
* // Stop the deferred function call (does nothing if it's not active).
41
* deferredCall.stop();
42
*
43
*/
44
45
46
goog.provide('goog.async.ConditionalDelay');
47
48
goog.require('goog.Disposable');
49
goog.require('goog.async.Delay');
50
51
52
53
/**
54
* A ConditionalDelay object invokes the associated function after a specified
55
* interval delay and checks its return value. If the function returns
56
* {@code true} the conditional delay is cancelled and {@see #onSuccess}
57
* is called. Otherwise this object keeps to invoke the deferred function until
58
* either it returns {@code true} or the timeout is exceeded. In the latter case
59
* the {@see #onFailure} method will be called.
60
*
61
* The interval duration and timeout can be specified each time the delay is
62
* started. Calling start on an active delay will reset the timer.
63
*
64
* @param {function():boolean} listener Function to call when the delay
65
* completes. Should return a value that type-converts to {@code true} if
66
* the call succeeded and this delay should be stopped.
67
* @param {Object=} opt_handler The object scope to invoke the function in.
68
* @constructor
69
* @struct
70
* @extends {goog.Disposable}
71
*/
72
goog.async.ConditionalDelay = function(listener, opt_handler) {
73
goog.async.ConditionalDelay.base(this, 'constructor');
74
75
/**
76
* The delay interval in milliseconds to between the calls to the callback.
77
* Note, that the callback may be invoked earlier than this interval if the
78
* timeout is exceeded.
79
* @private {number}
80
*/
81
this.interval_ = 0;
82
83
/**
84
* The timeout timestamp until which the delay is to be executed.
85
* A negative value means no timeout.
86
* @private {number}
87
*/
88
this.runUntil_ = 0;
89
90
/**
91
* True if the listener has been executed, and it returned {@code true}.
92
* @private {boolean}
93
*/
94
this.isDone_ = false;
95
96
/**
97
* The function that will be invoked after a delay.
98
* @private {function():boolean}
99
*/
100
this.listener_ = listener;
101
102
/**
103
* The object context to invoke the callback in.
104
* @private {Object|undefined}
105
*/
106
this.handler_ = opt_handler;
107
108
/**
109
* The underlying goog.async.Delay delegate object.
110
* @private {goog.async.Delay}
111
*/
112
this.delay_ = new goog.async.Delay(
113
goog.bind(this.onTick_, this), 0 /*interval*/, this /*scope*/);
114
};
115
goog.inherits(goog.async.ConditionalDelay, goog.Disposable);
116
117
118
/** @override */
119
goog.async.ConditionalDelay.prototype.disposeInternal = function() {
120
this.delay_.dispose();
121
delete this.listener_;
122
delete this.handler_;
123
goog.async.ConditionalDelay.superClass_.disposeInternal.call(this);
124
};
125
126
127
/**
128
* Starts the delay timer. The provided listener function will be called
129
* repeatedly after the specified interval until the function returns
130
* {@code true} or the timeout is exceeded. Calling start on an active timer
131
* will stop the timer first.
132
* @param {number=} opt_interval The time interval between the function
133
* invocations (in milliseconds). Default is 0.
134
* @param {number=} opt_timeout The timeout interval (in milliseconds). Takes
135
* precedence over the {@code opt_interval}, i.e. if the timeout is less
136
* than the invocation interval, the function will be called when the
137
* timeout is exceeded. A negative value means no timeout. Default is 0.
138
*/
139
goog.async.ConditionalDelay.prototype.start = function(
140
opt_interval, opt_timeout) {
141
this.stop();
142
this.isDone_ = false;
143
144
var timeout = opt_timeout || 0;
145
this.interval_ = Math.max(opt_interval || 0, 0);
146
this.runUntil_ = timeout < 0 ? -1 : (goog.now() + timeout);
147
this.delay_.start(
148
timeout < 0 ? this.interval_ : Math.min(this.interval_, timeout));
149
};
150
151
152
/**
153
* Stops the delay timer if it is active. No action is taken if the timer is not
154
* in use.
155
*/
156
goog.async.ConditionalDelay.prototype.stop = function() {
157
this.delay_.stop();
158
};
159
160
161
/**
162
* @return {boolean} True if the delay is currently active, false otherwise.
163
*/
164
goog.async.ConditionalDelay.prototype.isActive = function() {
165
return this.delay_.isActive();
166
};
167
168
169
/**
170
* @return {boolean} True if the listener has been executed and returned
171
* {@code true} since the last call to {@see #start}.
172
*/
173
goog.async.ConditionalDelay.prototype.isDone = function() {
174
return this.isDone_;
175
};
176
177
178
/**
179
* Called when the listener has been successfully executed and returned
180
* {@code true}. The {@see #isDone} method should return {@code true} by now.
181
* Designed for inheritance, should be overridden by subclasses or on the
182
* instances if they care.
183
*/
184
goog.async.ConditionalDelay.prototype.onSuccess = function() {
185
// Do nothing by default.
186
};
187
188
189
/**
190
* Called when this delayed call is cancelled because the timeout has been
191
* exceeded, and the listener has never returned {@code true}.
192
* Designed for inheritance, should be overridden by subclasses or on the
193
* instances if they care.
194
*/
195
goog.async.ConditionalDelay.prototype.onFailure = function() {
196
// Do nothing by default.
197
};
198
199
200
/**
201
* A callback function for the underlying {@code goog.async.Delay} object. When
202
* executed the listener function is called, and if it returns {@code true}
203
* the delay is stopped and the {@see #onSuccess} method is invoked.
204
* If the timeout is exceeded the delay is stopped and the
205
* {@see #onFailure} method is called.
206
* @private
207
*/
208
goog.async.ConditionalDelay.prototype.onTick_ = function() {
209
var successful = this.listener_.call(this.handler_);
210
if (successful) {
211
this.isDone_ = true;
212
this.onSuccess();
213
} else {
214
// Try to reschedule the task.
215
if (this.runUntil_ < 0) {
216
// No timeout.
217
this.delay_.start(this.interval_);
218
} else {
219
var timeLeft = this.runUntil_ - goog.now();
220
if (timeLeft <= 0) {
221
this.onFailure();
222
} else {
223
this.delay_.start(Math.min(this.interval_, timeLeft));
224
}
225
}
226
}
227
};
228
229