Skip to content

Instantly share code, notes, and snippets.

@saadtazi
Last active April 9, 2016 18:27
Show Gist options
  • Save saadtazi/74660c403166fa9cfb9ee7fe5b1f092b to your computer and use it in GitHub Desktop.
Save saadtazi/74660c403166fa9cfb9ee7fe5b1f092b to your computer and use it in GitHub Desktop.
Promise polling

Usage

promisePoll(
  // a function that takes no param and return a promise
  // `.bind(...)` as much a you want!
  () => { return aPromise; },
  // a function that will be called with the resolved value
  // of return value of the first function
  // and that should return true if the condition is satisfied
  (res) => { return res.prop = 'expectedValue'; },
  // wait: number of milliseconds between 2 function1 calls
  500,
  // failAfter: number of milliseconds between 2 function1 calls
  3000);

Gotcha

  • We do not garantee that this function will take a most failAfterms: if the condition is never satisfied and failAfter is not a multiple of wait, then the returned promise might fail after Math.ceil(failAfter / wait) * wait ( which is > failAfter)

This will resolve after ~600ms:

let a = 1;
setTimeout(() => { a = 2; }, 500);
return promisePoll(
  function () { return Promise.resolve(a); },
  (res) => res === 2,
  200,
  1000
);

This is rejected after ~1000ms, even if failedAfter is 900:

let a = 1;
setTimeout(() => { a = 2; }, 5000);
return promisePoll(
  function () { return Promise.resolve(a); },
  (res) => res === 2,
  200,
  900
);
import Bluebird from 'bluebird';
const hasExpired = (startedAt, failAfter) => {
return startedAt + failAfter < Date.now();
};
const PromisePoll = (promiseFunc, conditionFunction, wait = 500, failAfter = 4000) => {
const startedAt = Date.now();
return new Bluebird((resolve, reject) => {
// to fail "exactly" after `failAfter`,
// we have to reject in a `setInterval()`
const interval = setInterval(() => {
console.log('in setInterval...');
if (hasExpired(startedAt, failAfter)) {
clearInterval(interval);
reject(new Error(`Promise Poll: cannot meet the condition after ${failAfter}ms`));
}
}, wait);
// define a recursive function that gets executed
// until timeout or the condition is satisfied
const executeAndCheckCondition = () => {
return promiseFunc()
.then((res) => {
if (hasExpired(startedAt, failAfter)) {
// we already `reject()` in `setInterval()`
return;
}
if (conditionFunction(res)) {
// success
clearInterval(interval);
return resolve(res);
}
// no timeout and not satisfied? retry after `wait`ms
Bluebird.delay(wait).then(executeAndCheckCondition);
});
};
// execute the recursive function
executeAndCheckCondition();
});
};
export default PromisePoll;
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment