DEV Community

Discussion on: How SWR works behind the scenes

Collapse
 
zanehannanau profile image
ZaneHannanAU • Edited

A simple fn that aims to do a similar stale-while-revalidate thing:

// takes a request and a response mapping function. map must be able to accept a null value. Returns the network request (reload) on completion, a stale network request, or a cached network request.
function stale_while_revalidate(req, map, err = _=>{alert(_); throw _;}) {
  let most_recent = 0;
  req = typeof req === "string" ? {url: req} : {...req})
  let stale_cache = caches.match(new Request(req)).finally(() => most_recent > 0 ? null : (most_recent = 1));
  let stale_fetch = fetch(new Request({
    ...req,
    "cache": "force-cache"
  }))
  .finally(() => most_recent > 1
    ? null
    : (most_recent = 2));
  let reload_fetch = fetch(new Request({
    ...req,
    "cache": "reload"
  }))
  .finally(() => most_recent > 2
    ? null
    : (most_recent = 3));
  const _next = () => new Promise(r => setTimeout(r, 99))
  .then(_ => {
    let k = [];
    switch(most_recent) {
      // no breaks
      case 0: k.push(stale_cache);
      case 1: k.push(stale_fetch);
      case 2: k.push(reload_fetch);
    }
    let r = Promise.race(k);
    if (most_recent!=3) return r
      .finally(()=>{_next();});
    return r;
  }).then(map, err);
  _next();
  return reload_fetch
    .catch(_=>stale_fetch)
    .catch(_=>stale_cache)
    .then(map, err);
}
Enter fullscreen mode Exit fullscreen mode

This doesn't handle visibility change refresh, though. I typed it up on a phone so please be forgiving...

Collapse
 
zanehannanau profile image
ZaneHannanAU

Note that if you're writing a real-time API or similar; it's probably best to use an EventSource or WebSocket. EventSource is generally less work for the same output; though.