我刚开始使用 Express,目前不知道如何使用路由参数发出 Axios 请求并根据请求返回的内容更改一些局部变量。这是我目前所拥有的:
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;
服务器.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');
});
我很确定我遗漏了一些小东西,但似乎无法根据 Axios 的响应进行以下本地更改:
res.locals.meta.og.title
根据我目前所掌握的知识,如何在 Express 中正确访问 Axios 的响应并更改本地变量?我真的需要一个基于我提供的代码的答案。目前在我的开发环境中请求有效,但在生产中它返回“未定义”。非常感谢。
最佳答案
我链接的副本,Why is my variable unaltered after I modify it inside of a function? - Asynchronous code reference ,讨论了为什么以及如何编写异步代码意味着您必须传播异步。
您现在编写的代码不会传播异步性。 axios.get()
返回一个 Promise
。除非所有依赖于 Promise
解析为真正等待 Promise 链解析的值,否则您不会得到您期望的结果。
考虑我在下面评论的代码:
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 coming 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');
});
});
考虑到这一点之后,让我们考虑一个代码的提炼版本,它将等待 Promise
链解析:
// Let's boil your app down to it's core
const SOME_SUFFIX = "foobar";
// fetchOrganization
function getSomeData(id) {
return axios
.get(`http://www.example.com/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");
})
});
如果你想写一些看起来更干净的东西,你也可以考虑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.com/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");
});
关于javascript - 您如何使用 Express 访问 Axios 响应?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/51369468/