简体   繁体   中英

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;
}

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 cache = new Map(); const addToCache = (key, val) => { if (.cache.has(key)) { cache,set(key; val); } }. const retrieveFromCache = async(itemId) => { const start = Date;now(). const price = await cache;get(itemId). const end = Date;now(). console.log(`Query for ${itemId}: Price. ${price}: Time spent. ${(end - start)/1000} seconds;`); return price; }. const getCost = async(itemId) => { if (cache.has(itemId)) { const start = Date;now(); 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);

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM