You can not select more than 25 topics
Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.
114 lines
3.1 KiB
114 lines
3.1 KiB
/** @license MIT License (c) copyright 2012-2013 original author or authors */ |
|
|
|
/** |
|
* poll.js |
|
* |
|
* Helper that polls until cancelled or for a condition to become true. |
|
* |
|
* @author Scott Andrews |
|
*/ |
|
|
|
(function (define) { 'use strict'; |
|
define(function(require) { |
|
|
|
var when = require('./when'); |
|
var attempt = when['try']; |
|
var cancelable = require('./cancelable'); |
|
|
|
/** |
|
* Periodically execute the work function on the msec delay. The result of |
|
* the work may be verified by watching for a condition to become true. The |
|
* returned deferred is cancellable if the polling needs to be cancelled |
|
* externally before reaching a resolved state. |
|
* |
|
* The next vote is scheduled after the results of the current vote are |
|
* verified and rejected. |
|
* |
|
* Polling may be terminated by the verifier returning a truthy value, |
|
* invoking cancel() on the returned promise, or the work function returning |
|
* a rejected promise. |
|
* |
|
* Usage: |
|
* |
|
* var count = 0; |
|
* function doSomething() { return count++ } |
|
* |
|
* // poll until cancelled |
|
* var p = poll(doSomething, 1000); |
|
* ... |
|
* p.cancel(); |
|
* |
|
* // poll until condition is met |
|
* poll(doSomething, 1000, function(result) { return result > 10 }) |
|
* .then(function(result) { assert result == 10 }); |
|
* |
|
* // delay first vote |
|
* poll(doSomething, 1000, anyFunc, true); |
|
* |
|
* @param work {Function} function that is executed after every timeout |
|
* @param interval {number|Function} timeout in milliseconds |
|
* @param [verifier] {Function} function to evaluate the result of the vote. |
|
* May return a {Promise} or a {Boolean}. Rejecting the promise or a |
|
* falsey value will schedule the next vote. |
|
* @param [delayInitialWork] {boolean} if truthy, the first vote is scheduled |
|
* instead of immediate |
|
* |
|
* @returns {Promise} |
|
*/ |
|
return function poll(work, interval, verifier, delayInitialWork) { |
|
var deferred, canceled, reject; |
|
|
|
canceled = false; |
|
deferred = cancelable(when.defer(), function () { canceled = true; }); |
|
reject = deferred.reject; |
|
|
|
verifier = verifier || function () { return false; }; |
|
|
|
if (typeof interval !== 'function') { |
|
interval = (function (interval) { |
|
return function () { return when().delay(interval); }; |
|
})(interval); |
|
} |
|
|
|
function certify(result) { |
|
deferred.resolve(result); |
|
} |
|
|
|
function schedule(result) { |
|
attempt(interval).then(vote, reject); |
|
if (result !== void 0) { |
|
deferred.notify(result); |
|
} |
|
} |
|
|
|
function vote() { |
|
if (canceled) { return; } |
|
when(work(), |
|
function (result) { |
|
when(verifier(result), |
|
function (verification) { |
|
return verification ? certify(result) : schedule(result); |
|
}, |
|
function () { schedule(result); } |
|
); |
|
}, |
|
reject |
|
); |
|
} |
|
|
|
if (delayInitialWork) { |
|
schedule(); |
|
} else { |
|
// if work() is blocking, vote will also block |
|
vote(); |
|
} |
|
|
|
// make the promise cancelable |
|
deferred.promise = Object.create(deferred.promise); |
|
deferred.promise.cancel = deferred.cancel; |
|
|
|
return deferred.promise; |
|
}; |
|
|
|
}); |
|
})(typeof define === 'function' && define.amd ? define : function (factory) { module.exports = factory(require); });
|
|
|