• Skip to main content
  • Skip to primary sidebar
  • Skip to footer
  • About
  • Life
  • Tech
  • Travel
  • Work
  • Questions
  • Contact

Welcome

.

How can I avoid race condition when making cached Ajax calls

April 10, 2020 by

Questions › How can I avoid race condition when making cached Ajax calls
0
Vote Up
Vote Down
Garmaine asked 3 years ago

Since many public APIs such as GitHub public API has a request limit, so it makes sense for us to implement some cache mechanism to avoid unnecessary request calls. However I discovered that this might incur race condition.

I coded up an example to demonstrate the situation https://codesandbox.io/s/race-condition-9kynm?file=/src/index.js

Here I first implement a cachedFetch ,

const cachedFetch = (url, options) => {
  // Use the URL as the cache key to sessionStorage
  let cacheKey = url;
  let cached = sessionStorage.getItem(cacheKey);
  if (cached !== null) {
    console.log("reading from cache....");
    let response = new Response(new Blob([cached]));
    return Promise.resolve(response);
  }

  return fetch(url, options).then(async response => {
    if (response.status === 200) {
      let ct = response.headers.get("Content-Type");
      if (ct && (ct.includes("application/json") || ct.includes("text"))) {
        response
          .clone()
          .text()
          .then(content => {
            sessionStorage.setItem(cacheKey, content);
          });
      }
    }
    return response;
  });
};

It uses sessionStorage to cache the results.

And I am making the requests to Github API. The idea is simple, there is a Input and a p tag, and the Input has a event listener to listen for input changes and uses the input value to get the github user's name and the p will render the name on the page.

The race condition might occur in the following situation:

  1. User types jack in the input field, since this is the first time the user types jack so the result is not cached. The request will be made to fetch this jack user's Github profile
  2. Then the user types david in the input field, since this is also the first time the user types david so the result is not cached. The request will be made to fetch this david user's Github profile
  3. Finally the user types jack in the input field for the second time, since the result is already in the cache. The no request will be made and we can read the user profile from sessionStorage and render the result immediately.

Then you can image that, if the second request, i.e. request to fetch david's profile takes too long, user will see david end up being the final result rendered on the page even if his/her last search was for jack. This is because jack's result got overridden by the david's result which takes much longer to get back.

In my example, I used this function to simulate the user typing

async function userTyping() {
  sessionStorage.clear();
  inputEl.value = "jack";
  inputEl.dispatchEvent(new Event("input"));

  await sleep(100);
  inputEl.value = "david";
  inputEl.dispatchEvent(new Event("input"));

  await sleep(100);
  inputEl.value = "jack";
  inputEl.dispatchEvent(new Event("input"));
}

the sleep function is defined as

const sleep = ms => new Promise(resolve => setTimeout(resolve, ms));

Right now what I can think of is using debounce to avoid the situation when the user is typing too fast. However it doesn't solve the problem in the fundamental level.

Also we can use some global variable to keep track of the latest input value, and use that to check if the result we are about to render is from the latest input value. Somehow I just don't think this is an elegant solution to this problem.

Any suggestions are appreciated.

Are you looking for the answer?
Original Question and Possible Answers can be found on `http://stackoverflow.com`

Question Tags: caching, frontend, html, http, javascript

Please login or Register to submit your answer




Primary Sidebar

Tags

Advancements architecture beautiful life best building calling city commercial convenience employment Finances Cognitive decline Future gadgets Hidden Gems highway Home houses hydration Impact Innovations lamp lighting Mental health military tech Must-See New York City occupation Productivity recreation romance sepia shopping sippy cups smartphones social Technological breakthroughs technology toddlers Treasures turns Uncover Well-being Wonders Work Young onset dementia

Newsletter

Complete the form below, and we'll send you all the latest news.

Footer

Footer Funnies

Who knew that reading the footer could be such a hilarious adventure? As we navigate websites, books, and documents, we often stumble upon the unassuming space at the bottom, only to discover a treasure trove of amusement. In this side-splitting compilation, we present 100 jokes that celebrate the unsung hero of content – the footer. Get ready to chuckle, giggle, and maybe even snort as we dive into the world of footnotes, disclaimers, and hidden comedic gems. Brace yourself for a wild ride through the footer!

Recent

  • Unveiling the Enigma: Almost-Magical Lamp Lights Highway Turns
  • The Impact of Young Onset Dementia on Employment and Finances: Optimizing Post-Diagnostic Approaches
  • 11 Wonders of 2023 Technological Breakthrough – Unveiling the Future
  • Work from Home and Stay Mentally Sane – Achieve Productivity and Well-being
  • Hidden Gems of New York City – Uncover the Must-See Treasures!

Search

Tags

Advancements architecture beautiful life best building calling city commercial convenience employment Finances Cognitive decline Future gadgets Hidden Gems highway Home houses hydration Impact Innovations lamp lighting Mental health military tech Must-See New York City occupation Productivity recreation romance sepia shopping sippy cups smartphones social Technological breakthroughs technology toddlers Treasures turns Uncover Well-being Wonders Work Young onset dementia

Copyright © 2023