lib/travis-status-checker.js
function queryWithWait(query, valueIsPending, options) {
  const maxWaitMs = options && options.wait ? Number(options.wait) : 0;
  if (Number.isNaN(maxWaitMs)) {
    return Promise.reject(new TypeError('wait must be a number'));
  }
  if (maxWaitMs < 0) {
    return Promise.reject(new RangeError('wait must be non-negative'));
  }

  const startMs = Date.now();
  // Note:  Divide by 2 so we can double unconditionally below
  let nextWaitMs = POLL_TIME_START_MS / 2;

  function doQuery(cb) {
    query.get(cb);
  }

  return new Promise((resolve, reject) => {
    function checkBuild(err, result) {
      if (err) {
        reject(err);
        return;
      }

      if (maxWaitMs) {
        let isPending;
        try {
          isPending = valueIsPending(result);
        } catch (errPending) {
          reject(errPending);
          return;
        }

        if (isPending) {
          const nowMs = Date.now();
          const totalWaitMs = nowMs - startMs;
          if (totalWaitMs < maxWaitMs) {
            nextWaitMs = Math.min(
              nextWaitMs * 2,
              POLL_TIME_MAX_MS,
              maxWaitMs - totalWaitMs
            );
            setTimeout(doQuery, nextWaitMs, checkBuild);
            return;
          }
        }
      }

      resolve(result);
    }

    doQuery(checkBuild);
  });
}
function queryWithWait(query, valueIsPending, options) {
  const maxWaitMs = options && options.wait ? Number(options.wait) : 0;
  if (Number.isNaN(maxWaitMs)) {
    return Promise.reject(new TypeError('wait must be a number'));
  }
  if (maxWaitMs < 0) {
    return Promise.reject(new RangeError('wait must be non-negative'));
  }

  const startMs = Date.now();
  // Note:  Divide by 2 so we can double unconditionally below
  let nextWaitMs = POLL_TIME_START_MS / 2;

  function doQuery(cb) {
    query.get(cb);
  }

  return new Promise((resolve, reject) => {
    function checkBuild(err, result) {
      if (err) {
        reject(err);
        return;
      }

      if (maxWaitMs) {
        let isPending;
        try {
          isPending = valueIsPending(result);
        } catch (errPending) {
          reject(errPending);
          return;
        }

        if (isPending) {
          const nowMs = Date.now();
          const totalWaitMs = nowMs - startMs;
          if (totalWaitMs < maxWaitMs) {
            nextWaitMs = Math.min(
              nextWaitMs * 2,
              POLL_TIME_MAX_MS,
              maxWaitMs - totalWaitMs
            );
            setTimeout(doQuery, nextWaitMs, checkBuild);
            return;
          }
        }
      }

      resolve(result);
    }

    doQuery(checkBuild);
  });
}
Options for {@link TravisStatusQueryOptions}.

@typedef {{
wait: number|undefined
}} TravisStatusQueryOptions
@property {number=} wait The maximum amount of time during which to retry
while the response is pending (in milliseconds). (default: no retry)
 var TravisStatusQueryOptions; Performs a travis-ci query, retrying while pending, up to a given wait
time.
@param {!{get: callback}} query <code>travis-ci</code> resource to query.
@param {(function(!Object): boolean)=} valueIsPending Function which
determines if an API value is considered to be pending for retry purposes.
@param {TravisStatusQueryOptions=} options Query options.
@return {Promise<!Object>} Promise with the response content or Error.
@private