axios.spread() cache my API whereas axios.get() does not

Issue

I’m facing a weird situation where I need to call a bunch of my CMS API routes from my server in order to use their response.data into an object that will then be passed to my client side.

This is the code that caches my data: meaning that when I change a field on my CMS, that data that is being pulled is not updated.

The code is:

let baseUrl = "https://sismographie-cms.herokuapp.com/api/"
let locales = ["?locale=en", "?locale=fr"]

let links = [
  "contact-page",
  "keywords",
  "podcasts",
  "random-question-arrays",
  "featured-entries-headlines-anims",
  "main-text",
  "headline",
  "cookie-setting",
  "header-info-array",
  "random-question-prompt",
  "contact-page",
  "map-entry-right-text",
  "map-entry-left-text",
  "sponsor-logos",
  "credit",
  "projects-about-texts"
  ].map((ele, index) => {
  return {
    en: `${baseUrl + ele + locales[0]}`,
    fr: `${baseUrl + ele + locales[1]}`,
  }
});


let objectKeys = [
  "info",
  "keywords",
  "podcasts",
  "randomQuestions",
  "featuredEntries",
  "balladosSubtitle",
  "balladosTitles",
  "cookiesSetting",
  "headerInfoArray",
  "randomQuestionPrompt",
  "conctactPage",
  "mapEntryRightText",
  "mapEntryLeftText",
  "sponsorLogos",
  "credit",
  "ProjectsAboutText"
];


let getAxiosRequests = (locale) => {
  return links
  .map((ele, index) =>  {
    return axios.get(ele[locale])
  })
};



axios.all(getAxiosRequests("fr"))
.then(axios.spread((...responses) => {

  let cmsObjFr = mapToObject(objectKeys, responses);
  
  axios.all(getAxiosRequests("en"))
  .then(axios.spread(
    (...responses) => {
    let cmsObjEn = mapToObject(objectKeys, responses);
    console.log(cmsObjEn);
    app.get('/cms-routes', (req, res) => {
      res.json({fr: cmsObjFr, en: cmsObjEn})
    })
  })).catch(errors => {
    console.error(errors);
  });
})).catch(errors => {
  console.error(errors);
});

 const mapToObject = (objectKeys, responses) => { 
    return objectKeys.reduce( 
        (sum, key, index) => Object.assign(
        sum, { [key]: responses[index].data.data}),{} 
    ); 
 }; 

When I access the json object, I see that the field I just changed did not update.

When I individually call that same field’s CMS route, however, the response contains the updated version of the data:

app.get("/credits", (req, res ) => {
  console.log("/credits' call");
  axios.get("https://sismographie-cms.herokuapp.com/api/credit?locale=en")
    .then(data => res.json(data.data))
})

For, let’s say, the credit field, this method will give me the updated version I don’t have access when I’m using the axios.spread method.

Solution

The problem is that because you create your route handler (app.get("/cms-routes")) after retrieving data, the data it responds with is fixed and will never change.

You need to move the data retrieval logic into the route handler.

Also, as mentioned above axios.all() and axios.spread() are deprecated and should not be used.

const links = {
  info: "contact-page",
  keywords: "keywords",
  podcasts: "podcasts",
  randomQuestions: "random-question-arrays",
  featuredEntries: "featured-entries-headlines-anims",
  balladosSubtitle: "main-text",
  balladosTitles: "headline",
  cookiesSetting: "cookie-setting",
  headerInfoArray: "header-info-array",
  randomQuestionPrompt: "random-question-prompt",
  conctactPage: "contact-page",
  mapEntryRightText: "map-entry-right-text",
  mapEntryLeftText: "map-entry-left-text",
  sponsorLogos: "sponsor-logos",
  credit: "credit",
  ProjectsAboutText: "projects-about-texts",
};

const baseURL = "https://sismographie-cms.herokuapp.com/api/";

/**
 * Resolves with an array of single property objects, eg
 * [
 *   {
 *     info: {...}
 *   },
 *   {
 *     keywords: {...}
 *   },
 *   ...
 * ]
 */
const getAll = (locale) =>
  Promise.all(
    Object.entries(links).map(async ([key, link]) => ({
      [key]: (await axios.get(link, { baseURL, params: { locale } })).data.data,
    }))
  );

app.get("/cms-routes", async (req, res) => {
  const [fr, en] = await Promise.all([getAll("fr"), getAll("en")]);

  res.json({ fr: Object.assign(...fr), en: Object.assign(...en) });
});

I’ve taken the liberty of simplifying your data structures so your links and object keys are tightly coupled.

Answered By – Phil

This Answer collected from stackoverflow, is licensed under cc by-sa 2.5 , cc by-sa 3.0 and cc by-sa 4.0

Leave a Reply

(*) Required, Your email will not be published