function handleResult (
  dispatch,
  globalOpts,
  cacheKey,
  handler,
  opts,
  reqCacheControl,
  result
) {
  if (!result) {
    return handleUncachedResponse(dispatch, globalOpts, cacheKey, handler, opts, reqCacheControl)
  }

  const now = Date.now()
  if (now > result.deleteAt) {
    // Response is expired, cache store shouldn't have given this to us
    return dispatch(opts, new CacheHandler(globalOpts, cacheKey, handler))
  }

  const age = Math.round((now - result.cachedAt) / 1000)
  if (reqCacheControl?.['max-age'] && age >= reqCacheControl['max-age']) {
    // Response is considered expired for this specific request
    //  https://www.rfc-editor.org/rfc/rfc9111.html#section-5.2.1.1
    return dispatch(opts, handler)
  }

  // Check if the response is stale
  if (needsRevalidation(result, reqCacheControl)) {
    if (util.isStream(opts.body) && util.bodyLength(opts.body) !== 0) {
      // If body is a stream we can't revalidate...
      // TODO (fix): This could be less strict...
      return dispatch(opts, new CacheHandler(globalOpts, cacheKey, handler))
    }

    let withinStaleIfErrorThreshold = false
    const staleIfErrorExpiry = result.cacheControlDirectives['stale-if-error'] ?? reqCacheControl?.['stale-if-error']
    if (staleIfErrorExpiry) {
      withinStaleIfErrorThreshold = now < (result.staleAt + (staleIfErrorExpiry * 1000))
    }

    let headers = {
      ...opts.headers,
      'if-modified-since': new Date(result.cachedAt).toUTCString()
    }

    if (result.etag) {
      headers['if-none-match'] = result.etag
    }

    if (result.vary) {
      headers = {
        ...headers,
        ...result.vary
      }
    }

    // We need to revalidate the response
    return dispatch(
      {
        ...opts,
        headers
      },
      new CacheRevalidationHandler(
        (success, context) => {
          if (success) {
            sendCachedValue(handler, opts, result, age, context, true)
          } else if (util.isStream(result.body)) {
            result.body.on('error', () => {}).destroy()
          }
        },
        new CacheHandler(globalOpts, cacheKey, handler),
        withinStaleIfErrorThreshold
      )
    )
  }

  // Dump request body.
  if (util.isStream(opts.body)) {
    opts.body.on('error', () => {}).destroy()
  }

  sendCachedValue(handler, opts, result, age, null, false)
}
@param {DispatchFn} dispatch
@param {import('../../types/cache-interceptor.d.ts').default.CacheHandlerOptions} globalOpts
@param {import('../../types/cache-interceptor.d.ts').default.CacheKey} cacheKey
@param {import('../../types/dispatcher.d.ts').default.DispatchHandler} handler
@param {import('../../types/dispatcher.d.ts').default.RequestOptions} opts
@param {import('../../types/cache-interceptor.d.ts').default.CacheControlDirectives | undefined} reqCacheControl
@param {import('../../types/cache-interceptor.d.ts').default.GetResult | undefined} result