最新消息:雨落星辰是一个专注网站SEO优化、网站SEO诊断、搜索引擎研究、网络营销推广、网站策划运营及站长类的自媒体原创博客

javascript - How do you access Axios response with Express? - Stack Overflow

programmeradmin3浏览0评论

I just started working with Express and am currently lost on how to make an Axios request using route parameters and change some locals based on what the request returns. This is what I have so far:

helpers.js

const axios = require('axios');
const {
  titleSuffix,
  organizationPath,
  varietyPath
} = require('./constants');

let organizationData = {};
let varietyData = {};

const Helpers = {

  fetchOrganization: (organizationID) => {
    axios.get(organizationPath + organizationID)
      .then( (response) => {
        //console.log(response);
        organizationData = response.data.data;
      })
      .catch( (error) => {
        //console.log(error);
      });
      return organizationData;
  },

  fetchVariety: (varietyID) => {
    axios.get(varietyPath + varietyID)
      .then( (response) => {
        //console.log(response);
        varietyData = response.data.data;
      })
      .catch( (error) => {
        //console.log(error);
      });
      return varietyData;
  },

  setOrgOpenGraphTags: (growerHash, res) => {
    Helpers.fetchOrganization(growerHash);
    res.locals.meta.og.title = organizationData.name + titleSuffix;
    console.log('Org = ' + organizationData.name);
  },

  setVarOpenGraphTags: (contextualId, res) => {
    Helpers.fetchVariety(contextualId);
    res.locals.meta.og.title = varietyData.name + titleSuffix;
    console.log('Var = ' + varietyData.name);
  }

};

module.exports = Helpers;

server.js

// Express
const express = require('express');
const app = express();

// Helpers
const {
  setOrgOpenGraphTags,
  setVarOpenGraphTags
} = require('./helpers');

// Organization
app.get(['/org/:growerHash/*', '/_org/:growerHash/*'], (req, res) => {
  setOrgOpenGraphTags(req.params.growerHash, res);
  res.render('org');
});

I'm fairly certain I'm missing something small but can't seem to get the following local changed based on the response from Axios:

res.locals.meta.og.title

Based on what I have so far how do I properly access the response from Axios in Express and change the locals? I really need an answer based around the code I've provided. Currently in my dev environment the request works but in production it returns "undefined". Thanks so much in advance.

I just started working with Express and am currently lost on how to make an Axios request using route parameters and change some locals based on what the request returns. This is what I have so far:

helpers.js

const axios = require('axios');
const {
  titleSuffix,
  organizationPath,
  varietyPath
} = require('./constants');

let organizationData = {};
let varietyData = {};

const Helpers = {

  fetchOrganization: (organizationID) => {
    axios.get(organizationPath + organizationID)
      .then( (response) => {
        //console.log(response);
        organizationData = response.data.data;
      })
      .catch( (error) => {
        //console.log(error);
      });
      return organizationData;
  },

  fetchVariety: (varietyID) => {
    axios.get(varietyPath + varietyID)
      .then( (response) => {
        //console.log(response);
        varietyData = response.data.data;
      })
      .catch( (error) => {
        //console.log(error);
      });
      return varietyData;
  },

  setOrgOpenGraphTags: (growerHash, res) => {
    Helpers.fetchOrganization(growerHash);
    res.locals.meta.og.title = organizationData.name + titleSuffix;
    console.log('Org = ' + organizationData.name);
  },

  setVarOpenGraphTags: (contextualId, res) => {
    Helpers.fetchVariety(contextualId);
    res.locals.meta.og.title = varietyData.name + titleSuffix;
    console.log('Var = ' + varietyData.name);
  }

};

module.exports = Helpers;

server.js

// Express
const express = require('express');
const app = express();

// Helpers
const {
  setOrgOpenGraphTags,
  setVarOpenGraphTags
} = require('./helpers');

// Organization
app.get(['/org/:growerHash/*', '/_org/:growerHash/*'], (req, res) => {
  setOrgOpenGraphTags(req.params.growerHash, res);
  res.render('org');
});

I'm fairly certain I'm missing something small but can't seem to get the following local changed based on the response from Axios:

res.locals.meta.og.title

Based on what I have so far how do I properly access the response from Axios in Express and change the locals? I really need an answer based around the code I've provided. Currently in my dev environment the request works but in production it returns "undefined". Thanks so much in advance.

Share Improve this question edited Jul 18, 2018 at 20:53 nunya asked Jul 16, 2018 at 20:13 nunyanunya 3151 gold badge5 silver badges17 bronze badges 3
  • Possible duplicate of Why is my variable unaltered after I modify it inside of a function? - Asynchronous code reference – zero298 Commented Jul 18, 2018 at 20:03
  • fetchOrganization is asynchronous and you aren't waiting on it. – zero298 Commented Jul 18, 2018 at 20:04
  • @zero298 has got you covered here. His answer gives you everything you need, so I remend that you read it thoroughly and then accept it - You're unlikely to get any more answers on this. – Kirk Larkin Commented Jul 18, 2018 at 21:15
Add a ment  | 

1 Answer 1

Reset to default 13 +50

The duplicate that I linked, Why is my variable unaltered after I modify it inside of a function? - Asynchronous code reference, discusses why and how writing asynchronous code means that you have to propagate being asynchronous.

Your code, as it is written right now, does not propagate asynchronicity. axios.get() returns a Promise. Unless everything that depends on the value that that Promise resolves to actually waits for the Promise chain to resolve, you aren't going to get what you are expecting.

Consider your code which I have mented below:

const axios = require('axios');

const Helpers = {
  fetchOrganization: (organizationID) => {
    // axios.get() will return a Promise
    // You have to wait for the Promise to finish before
    // you can use any data that it produces
    // You must propogate the Proise of data up

    // You should return axios.get(...)
    axios.get(organizationPath + organizationID)
      .then((response) => {
        //console.log(response);
        organizationData = response.data.data;
      })
      .catch((error) => {
        //console.log(error);
      });
    // This won't be populated by the time you try to use it
    return organizationData;

    // Instead do
    return axios
      .get(organizationPath + organizationID)
      .then(response => {
        const organizationData = response.data.data;
        return organizationData
      })
      .catch(err => console.error(err));

    // Better yet, do
    /*
    return axios.get(organizationPath + organizationID)
        .then(res => response.data.data) // Return is implied
        .catch(err => console.error(err));
    */
  },

  setOrgOpenGraphTags: (growerHash, res) => {
    // Nothing is ing out of this function and you aren't waiting on it
    Helpers.fetchOrganization(growerHash);

    // Instead do
    return Helpers.fetchOrganization(growerHash)
      .then(org => {
        return org.name + titleSuffix;
      });

    //res.locals.meta.og.title = organizationData.name + titleSuffix;
    //console.log('Org = ' + organizationData.name);
  }
}

// Organization
app.get(['/org/:growerHash/*', '/_org/:growerHash/*'], (req, res) => {
  // Below, you are starting the async process
  // but you don't wait for the async to finish
  // you just immediately res.render()
  setOrgOpenGraphTags(req.params.growerHash, res);
  res.render('org');

  // Instead
  setOrgOpenGraphTags(req.params.growerHash, res)
    .then(orgTitle => {
      res.locals.meta.og.title = orgTitle;
      res.render('org');
    });
});

After considering that, let's consider a distilled version of your code that will wait for the Promise chain to resolve:

// Let's boil your app down to it's core
const SOME_SUFFIX = "foobar";

// fetchOrganization
function getSomeData(id) {
  return axios
    .get(`http://www.example./things/${id}`)
    .then(thatThing => thatThing.nested.property.i.want)
    .catch(err => console.error(err));
}

// setOrgOpenGraphTags
function calculateDerivedData(id) {
  return getSomeData(id)
    .then(thatThingsProperty => `${thatThingsProperty}-${SOME_SUFFIX}`)
}

// Route
app.get("/some/endpoint/:id", (req, res) => {
  calculateDerivedData(req.params.id)
    .then(thatDerivedDataWeNeed => {
      res.locals.whatever = thatDerivedDataWeNeed;
      res.render("someTemplate");
    })
});

If you want to write something that looks arguably cleaner, you can also consider async/await:

// Let's boil your app down to it's core
const SOME_SUFFIX = "foobar";

// fetchOrganization
async function getSomeData(id) {
    try {
        const thatThing = await axios.get(`http://www.example./things/${id}`);
        return thatThing.nested.property.i.want;
    } catch(err){
        console.error(err);
    }
}

// setOrgOpenGraphTags
async function calculateDerivedData(id) {
    const thatThingsProperty = await getSomeData(id);
    return `${thatThingsProperty}-${SOME_SUFFIX}`;
}

// Route
app.get("/some/endpoint/:id", async function(req, res) => {
  res.locals.whatever = await calculateDerivedData(req.params.id);
  res.render("someTemplate");
});
发布评论

评论列表(0)

  1. 暂无评论