function retry(
  fn,
  options = {
    delay: 1000,
    // sig: (error: Error, retries: number) -> boolean
    check: () => false,
  },
  retries = 0
) {
  return new Promise((resolve, reject) => {
    fn()
      .then(resolve)
      .catch((error) => {
        // If the check is satisfied, call reject to stop the retry cycle.
        if (options.check && options.check(error, retries)) {
          reject(error);
        }

        // Delay before the next retry.
        setTimeout(() => {
          retry(fn, options, retries + 1).then(resolve, reject);
        }, options.delay);
      });
  });
}
Takes a function that returns a promise and handles retrying until some
check condition is met.