Business
Jobs
  • About Us
  • Solutions
    • Job Postings
      Post your job and receive qualified candidates in 48h.
    • Candidate Assessments
      500+ technical and psychological tests, plus anti-fraud.
    • Headhunting
      Tailor-made executive search from start to finish.
    • Payroll + EOR
      Payroll dispersal and EOR across 15+ LATAM countries.
  • Pricing
  • Jobs

0

140
Views
Detecting an in-flight request to an API in Nodejs

I am writing a service in Nodejs in which I fetch prices from an Api and the call to the API might take over a minute so one of the things that can happen is that a request for a specific item can happen and the same item can be requested before the first item is returned and I want to detect if there is an in-flight request for a specified item and, if there is one, I need to wait for this request to be finished and return the same response for both requests.

An example diagram would be:

00.000 getCost('123') #1 call
00.001 getExternalCost('123') query
01.000 getCost('123') #2 call
90.001 getExternalCost('123') response
90.002 getCost('123') #1 response
90.003 getCost('123') #2 response

This is the code I have written so far, which simply fetches the cost of the item.

let cache = new Map();
let addToCache = (key,val) => {
  if(!cache.has(key)){
    cache.set(key,val);
  }
}

const getCost = async (itemId) => {

  if(cache.has(itemId)){
    return cache.get(itemId);
  }

  const price = await getExternalCost(itemId);
  addToCache(itemId,price);
  
  return cost;
}
about 4 years ago · Juan Pablo Isaza
1 answers
Answer question

0

This can be done if you add promises to the cache rather than awaiting them. By doing this an incoming query can be redirected to receive the value of a similar query pending in the cache.

const MAX_AGE = 1000;
const cache = new Map();

const cacheContainsKey = key => {
  if (!cache.has(key)) {
    return false;
  }

  const {
    _ts
  } = cache.get(key);
  const age = Date.now() - _ts;
  if (age <= MAX_AGE) {
    return true;
  }

  console.log(`key ${key} age exceeds MAX_AGE: ${age}. Deleting key from cache.`);
  cache.delete(key);
  return false;
};

const addToCache = (key, val) => {
  cache.set(key, {
    _ts: Date.now(),
    val
  });
};

const retrieveFromCache = async(itemId) => {
  try {
    const start = Date.now();
    const price = await cache.get(itemId).val;
    const end = Date.now();
    console.log(`Query for ${itemId}. Price: ${price}. Time spent: ${(end - start) / 1000} seconds.`);
    return price;
  } catch (err) {
    /*
      If required insert logic here to remove the itemId from the cache to
      allow new attempts to getExternalCost on this itemId.
    */
    return err;
  }
};

const getCost = async(itemId) => {
  if (cacheContainsKey(itemId)) {
    const price = await retrieveFromCache(itemId);
    return price;
  }

  const pricePromise = getExternalCost(itemId);
  addToCache(itemId, pricePromise);

  // all queries go through the cache
  const price = await retrieveFromCache(itemId);
  return price;
};


// example code
function getExternalCost(itemId) {
  return new Promise((resolve, __reject) => {
    setTimeout(() => {
      resolve(itemId * 100);
    }, 1000);
  });
}

let counter = 0;
const itemIds = [10, 10, 12, 12, 10, 1];

// mimic incoming queries
let interval = setInterval(() => {
  getCost(itemIds[counter++]);
  if (counter === itemIds.length) {
    clearInterval(interval);
  }
}, 500);

about 4 years ago · Juan Pablo Isaza Report
Answer question
Find remote jobs

Discover the new way to find a job!

Top jobs
Top job categories
Business
Post vacancy Pricing Sales
Legal
Terms and conditions Privacy policy
© 2026 PeakU Inc. All Rights Reserved.
Andres GPT
Show me some job opportunities
There's an error!