Skip to content

Instantly share code, notes, and snippets.

@joeyjiron06
Last active November 29, 2018 19:35
Show Gist options
  • Save joeyjiron06/1532b20557850ea1b98f7d5f1b12bd70 to your computer and use it in GitHub Desktop.
Save joeyjiron06/1532b20557850ea1b98f7d5f1b12bd70 to your computer and use it in GitHub Desktop.
poller.js - simple javascript poller
{
"name": "poller",
"version": "1.0.0",
"description": "",
"main": "poller.js",
"dependencies": {},
"devDependencies": {
"chai": "^4.1.2",
"mocha": "^5.1.1"
},
"scripts": {
"test": "mocha *.test.js"
},
"author": "",
"license": "ISC"
}
/**
* A super simple polling function. It takes in a function that should be called with a specified delay.
* This function returns a function that, when invoked, will cancel and pending timeouts/polling and will
* block all subsequent calls from firing a poll event
* @example
* this.cancelPolling = poller(poll => {
* fetchUserLogin()
* .then(data => {
* if (!data.hasLoggedIn) {
* poll(5000);
* } else {
* this.onUserLoggedIn(data);
* }
* })
* .catch(err => {
* poll(10000); // poll longer on errors
* });
* });
*
* ...
* onCancelButtonClicked() {
* if (this.cancelPolling) {
* this.cancelPolling();
* this.cancelPolling = null;
* }
* }
*
*
* @param {function} fn - a function that is invoked after each delay
* @return {function} a function that, when invoked, will cancel any pending poll
*/
module.exports = fn => {
let isCancelled = false;
let timer = null;
const cancel = () => {
if (!isCancelled) {
clearTimeout(timer);
timer = null;
isCancelled = true;
}
};
const pollDelayed = delayMillis => {
clearTimeout(timer);
timer = setTimeout(() => {
if (isCancelled) {
return;
}
fn(pollDelayed);
}, delayMillis);
};
fn(pollDelayed);
return cancel;
};
const { expect } = require("chai");
const poller = require("./poller");
describe("poller", () => {
it("should return a function", () => {
expect(typeof poller(() => {})).to.equal("function");
});
it("should poll after the specified delay", done => {
const start = Date.now();
const delay = 100;
let count = 0;
poller(poll => {
if (count === 3) {
const duration = Date.now() - start;
expect(duration).to.be.greaterThan(count * delay);
done();
return;
}
count++;
poll(100);
});
});
it("should cancel the polling", done => {
const pollDelayMillis = 100;
const maxCount = 5;
let count = 0;
const cancel = poller(poll => {
if (++count === maxCount) {
cancel();
}
poll(pollDelayMillis);
});
setTimeout(() => {
expect(count).to.equal(5);
done();
}, pollDelayMillis * (maxCount + 2));
});
it("should poll once if cancelled immediately", done => {
let count = 0;
const cancel = poller(poll => {
count++;
poll(10);
});
cancel();
setTimeout(() => {
expect(count).to.equal(1);
done();
}, 50);
});
it("should protect against calling poll mutiple times in the callback", done => {
let count = 0;
poller(poll => {
if (++count === 5) {
return;
}
poll(10);
poll(10);
poll(10);
});
setTimeout(() => {
expect(count).to.equal(5);
done();
}, 100);
});
});
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment