合并来自链式 axios 请求的两个数组
Merging two arrays from chained axios requests
我正在将一堆 axios get 请求链接到 API 的不同端点,我正在尝试从数据(简化)创建一个这样的数组:
[
{
name: "John",
id: 1,
gender: "male"
},
{
name: "Anna",
id: 2,
gender: "female"
},
]
在其中一个请求中,我在一个数组中检索每个人的姓名和 ID,如下所示:
[
{
name: "John",
id: 1
},
{
name: "Anna",
id: 2
},
]
现在我只需要通过在两个单独的请求中将每个人的 ID 发送到端点来获取他们的性别。
我花了几个小时试图用 push() 和 then() 在顶部构造数组,但我就是做不对。
我该怎么做?
我正在像这样链接 axios 请求顺便说一句:
axios.get('api/' + endpoint1]).then(response => {
axios.get('api/' + endpoint2).then(response => {
axios.get('api/' + endpoint3).then(response => {
// and so on...
});
});
});
更新 1:
我觉得我没有把问题解释清楚。这就是我的代码现在的样子,从最后一个承诺开始。我怎样才能更改它以使数组位于问题的顶部?
.then(response => {
people= response.data; // Array of people including their name id (not their gender though)
for (var key in people) {
var person = {};
person["name"] = people[key].node.name;
person["id"] = people[key].node.id;
finalArray.push(person);
axios.get('api/' + endpoint3, { // Endpoint for getting a persons gender from id
params: {
personId: person.id
}
}).then(response => {
// I don't know what to do here...
});
}
console.log(finalArray); // Gives me an array of objects without "gender".
});
更新 2:
非常感谢您的回答!
我结合了您的一些解决方案,这就是我的 真实 代码现在的样子。未发送对 http://api.ntjp.se/coop/api/v1/serviceProducers.json 的请求。 为什么?
我也不想在调用 http://api.ntjp.se/coop/api/v1/serviceProducers.json 之前将整个对象保留在合作响应数组中。我只想从每个对象中保存两个特定的 key/value 对。这两个 key/value 对都在每个响应对象中名为 "serviceContract" 的对象中。 如何保存它们?
<html>
<head>
<script src="https://unpkg.com/axios/dist/axios.min.js"></script>
</head>
<body>
<script>
getConnectionStatusData();
async function getConnectionStatusData() {
let serviceDomains = await axios.get('http://api.ntjp.se/coop/api/v1/serviceDomains.json', {
params: {
namespace: "crm:scheduling"
}
});
serviceDomainId = serviceDomains.data[0].id;
let connectionPoints = await axios.get('http://api.ntjp.se/coop/api/v1/connectionPoints.json', {
params: {
platform: "NTJP",
environment: "PROD"
}
});
connectionPointId = connectionPoints.data[0].id;
let logicalAddresss = await axios.get('http://api.ntjp.se/coop/api/v1/logicalAddresss.json', {
params: {
logicalAdress: "SE2321000016-167N",
serviceConsumerHSAId: "SE2321000016-92V4",
connectionPointId: connectionPointId
}
});
logicalAddressId = logicalAddresss.data[0].id;
let serviceConsumers = await axios.get('http://api.ntjp.se/coop/api/v1/serviceConsumers.json', {
params: {
connectionPointId: connectionPointId,
logicalAddressId: logicalAddressId
}
});
consumer = serviceConsumers.data.filter(obj => {
return obj.hsaId === "SE2321000016-92V4"
});
serviceConsumerId = consumer[0].id;
let cooperations = await axios.get('http://api.ntjp.se/coop/api/v1/cooperations.json', {
params: {
connectionPointId: connectionPointId,
logicalAddressId: logicalAddressId,
serviceDomainId: serviceDomainId,
serviceConsumerId: serviceConsumerId,
include: "serviceContract"
}
});
for(var idx in cooperations.data) {
var data = async () => { return await axios.get('http://api.ntjp.se/coop/api/v1/serviceProducers.json', {
params: {
connectionPointId: connectionPointId,
logicalAddressId: logicalAddressId,
serviceDomainId: serviceDomainId,
serviceConsumerId: serviceConsumerId,
serviceContractId: cooperations.data[idx].serviceContract.id
}
}) }
cooperations.data[idx].producerDescription = data.description;
cooperations.data[idx].producerHSAId = data.hsaId;
}
console.log(cooperations.data);
}
</script>
</body>
更新 3
我终于成功了,但是为什么最后推入finalResult的时候还要引用response.data[0].description
这样的数据呢?我的意思是,为什么 response.data.description
不像 @Cold Cerberus 那样有效?
除此之外,我的代码是否正常,还是我做错了什么?
谢谢大家!
<html>
<head>
<script src="https://unpkg.com/axios/dist/axios.min.js"></script>
</head>
<body>
<script>
getConnectionStatusData();
async function getConnectionStatusData() {
let serviceDomains = await axios.get('http://api.ntjp.se/coop/api/v1/serviceDomains.json', {
params: {
namespace: "crm:scheduling"
}
});
serviceDomainId = serviceDomains.data[0].id;
let connectionPoints = await axios.get('http://api.ntjp.se/coop/api/v1/connectionPoints.json', {
params: {
platform: "NTJP",
environment: "PROD"
}
});
connectionPointId = connectionPoints.data[0].id;
let logicalAddresss = await axios.get('http://api.ntjp.se/coop/api/v1/logicalAddresss.json', {
params: {
logicalAdress: "SE2321000016-167N",
serviceConsumerHSAId: "SE2321000016-92V4",
connectionPointId: connectionPointId
}
});
logicalAddressId = logicalAddresss.data[0].id;
let serviceConsumers = await axios.get('http://api.ntjp.se/coop/api/v1/serviceConsumers.json', {
params: {
connectionPointId: connectionPointId,
logicalAddressId: logicalAddressId
}
});
consumer = serviceConsumers.data.filter(obj => {
return obj.hsaId === "SE2321000016-92V4"
});
serviceConsumerId = consumer[0].id;
let cooperations = await axios.get('http://api.ntjp.se/coop/api/v1/cooperations.json', {
params: {
connectionPointId: connectionPointId,
logicalAddressId: logicalAddressId,
serviceDomainId: serviceDomainId,
serviceConsumerId: serviceConsumerId,
include: "serviceContract"
}
});
var finalData = [];
cooperations.data.forEach(function(cooperation) {
axios.get('http://api.ntjp.se/coop/api/v1/serviceProducers.json', {
params: {
connectionPointId: connectionPointId,
logicalAddressId: logicalAddressId,
serviceDomainId: serviceDomainId,
serviceConsumerId: serviceConsumerId,
serviceContractId: cooperation.serviceContract.id
}
}).then(response => {
finalData.push({serviceContract: cooperation.serviceContract.namespace, serviceProducerDescription: response.data[0].description, serviceProducerHSAId: response.data[0].hsaId});
});
});
console.log(finalData);
}
</script>
</body>
我不太确定你的具体问题。但是假设你的意思是你有两个端点,第一个是 returns 一个对象数组(我们称之为 'getPeopleArray'
):
[
{
name: "John",
id: 1
},
{
name: "Anna",
id: 2
}
]
和第二个端点 returns 给定 id
的 gender
(让我们用一个参数 id
称它为 'getGender'
),.push
不会为您完成这项工作。
您的问题可以通过以下方式解决:
let peopleArray = [];
axios.get('api/' + 'getPeopleArray').then(people => {
peopleArray = people;
people.forEach((person, index) => {
axios.get('api/' + 'getGender?id='.concat(person.id.toString()))
.then(gender => {
peopleArray[index].gender = gender;
});
});
});
首先是您保存第一个请求的返回数组,然后您必须遍历该数组中的每个对象,使用 index
从第二个端点获取并分配它们的 genders
你的 [].forEach(callbackfn)
的论点。只要在所有请求完成期间或之前没有对 peopleArray
进行操作,索引就是正确的。
更新二:
为了回应您在评论 "why .push doesn't work?" 中提出的问题,我决定采用另一种方法如果您想使用 .push
结束您的算法并且不使用跟踪索引。
let peopleArray = [];
axios.get('api/' + 'getPeopleArray').then(people => {
people.forEach((person) => {
axios.get('api/' + 'getGender?id='.concat(person.id.toString()))
.then(gender => {
peopleArray.push({id: person.id, name: person.name, gender, gender});
});
});
});
这样,您只会在对象的性别也被提取时将其推送到您的集合 peopleArray
。这也将消除必须使用 .map
(如评论中建议的那样)来仅存储您希望保留的单个对象的属性,因为您在行 peopleArray.push({id: person.id, name: person.name, gender, gender});
.
上推送了一个新的结构化对象
我不喜欢阅读链式承诺,而是更喜欢使用 async/await
。您可以先获取您的列表,然后使用 map
遍历该列表并请求每个名称的性别。请记住,在继续之前,您必须等待 map
中的所有承诺都得到解决。
const axios = require('axios');
async function getPeople() {
let firstResult = await axios.get('api/path/endpoint1');
// firstResult = [{name: "John", id: 1}, {name: "Anna", id: 2}]
let updatedResult = firstResult.map(async item => {
let people = await axios.get('api/path/endpoint2' + item.name); // or however your endpoint is designed
// people = {name: "John", id: 1, gender: male}
item.gender = people.gender;
return item;
});
// updatedResult = undefined
Promise.all(updatedResult)
.then(finalResult => console.log(finalResult));
// [{name: "John", id: 1, gender: male}, {name: "Anna", id: 2, gender: female}]
}
您可以使用 async/awaits 并将 gender
密钥重新分配给第一个端点数据...
var users;
axios.get('api/' + endpoint1]).then(response => {
users = response; // assume all user id list
for(var idx in users) {
var data = async () => { return await axios.get('api/' + users[idx].id) } //get gender api by user id
users[idx].gender = data.gender; //create gender key value
}
console.log(users);
});
我正在将一堆 axios get 请求链接到 API 的不同端点,我正在尝试从数据(简化)创建一个这样的数组:
[
{
name: "John",
id: 1,
gender: "male"
},
{
name: "Anna",
id: 2,
gender: "female"
},
]
在其中一个请求中,我在一个数组中检索每个人的姓名和 ID,如下所示:
[
{
name: "John",
id: 1
},
{
name: "Anna",
id: 2
},
]
现在我只需要通过在两个单独的请求中将每个人的 ID 发送到端点来获取他们的性别。
我花了几个小时试图用 push() 和 then() 在顶部构造数组,但我就是做不对。
我该怎么做?
我正在像这样链接 axios 请求顺便说一句:
axios.get('api/' + endpoint1]).then(response => {
axios.get('api/' + endpoint2).then(response => {
axios.get('api/' + endpoint3).then(response => {
// and so on...
});
});
});
更新 1:
我觉得我没有把问题解释清楚。这就是我的代码现在的样子,从最后一个承诺开始。我怎样才能更改它以使数组位于问题的顶部?
.then(response => {
people= response.data; // Array of people including their name id (not their gender though)
for (var key in people) {
var person = {};
person["name"] = people[key].node.name;
person["id"] = people[key].node.id;
finalArray.push(person);
axios.get('api/' + endpoint3, { // Endpoint for getting a persons gender from id
params: {
personId: person.id
}
}).then(response => {
// I don't know what to do here...
});
}
console.log(finalArray); // Gives me an array of objects without "gender".
});
更新 2:
非常感谢您的回答!
我结合了您的一些解决方案,这就是我的 真实 代码现在的样子。未发送对 http://api.ntjp.se/coop/api/v1/serviceProducers.json 的请求。 为什么?
我也不想在调用 http://api.ntjp.se/coop/api/v1/serviceProducers.json 之前将整个对象保留在合作响应数组中。我只想从每个对象中保存两个特定的 key/value 对。这两个 key/value 对都在每个响应对象中名为 "serviceContract" 的对象中。 如何保存它们?
<html>
<head>
<script src="https://unpkg.com/axios/dist/axios.min.js"></script>
</head>
<body>
<script>
getConnectionStatusData();
async function getConnectionStatusData() {
let serviceDomains = await axios.get('http://api.ntjp.se/coop/api/v1/serviceDomains.json', {
params: {
namespace: "crm:scheduling"
}
});
serviceDomainId = serviceDomains.data[0].id;
let connectionPoints = await axios.get('http://api.ntjp.se/coop/api/v1/connectionPoints.json', {
params: {
platform: "NTJP",
environment: "PROD"
}
});
connectionPointId = connectionPoints.data[0].id;
let logicalAddresss = await axios.get('http://api.ntjp.se/coop/api/v1/logicalAddresss.json', {
params: {
logicalAdress: "SE2321000016-167N",
serviceConsumerHSAId: "SE2321000016-92V4",
connectionPointId: connectionPointId
}
});
logicalAddressId = logicalAddresss.data[0].id;
let serviceConsumers = await axios.get('http://api.ntjp.se/coop/api/v1/serviceConsumers.json', {
params: {
connectionPointId: connectionPointId,
logicalAddressId: logicalAddressId
}
});
consumer = serviceConsumers.data.filter(obj => {
return obj.hsaId === "SE2321000016-92V4"
});
serviceConsumerId = consumer[0].id;
let cooperations = await axios.get('http://api.ntjp.se/coop/api/v1/cooperations.json', {
params: {
connectionPointId: connectionPointId,
logicalAddressId: logicalAddressId,
serviceDomainId: serviceDomainId,
serviceConsumerId: serviceConsumerId,
include: "serviceContract"
}
});
for(var idx in cooperations.data) {
var data = async () => { return await axios.get('http://api.ntjp.se/coop/api/v1/serviceProducers.json', {
params: {
connectionPointId: connectionPointId,
logicalAddressId: logicalAddressId,
serviceDomainId: serviceDomainId,
serviceConsumerId: serviceConsumerId,
serviceContractId: cooperations.data[idx].serviceContract.id
}
}) }
cooperations.data[idx].producerDescription = data.description;
cooperations.data[idx].producerHSAId = data.hsaId;
}
console.log(cooperations.data);
}
</script>
</body>
更新 3
我终于成功了,但是为什么最后推入finalResult的时候还要引用response.data[0].description
这样的数据呢?我的意思是,为什么 response.data.description
不像 @Cold Cerberus 那样有效?
除此之外,我的代码是否正常,还是我做错了什么?
谢谢大家!
<html>
<head>
<script src="https://unpkg.com/axios/dist/axios.min.js"></script>
</head>
<body>
<script>
getConnectionStatusData();
async function getConnectionStatusData() {
let serviceDomains = await axios.get('http://api.ntjp.se/coop/api/v1/serviceDomains.json', {
params: {
namespace: "crm:scheduling"
}
});
serviceDomainId = serviceDomains.data[0].id;
let connectionPoints = await axios.get('http://api.ntjp.se/coop/api/v1/connectionPoints.json', {
params: {
platform: "NTJP",
environment: "PROD"
}
});
connectionPointId = connectionPoints.data[0].id;
let logicalAddresss = await axios.get('http://api.ntjp.se/coop/api/v1/logicalAddresss.json', {
params: {
logicalAdress: "SE2321000016-167N",
serviceConsumerHSAId: "SE2321000016-92V4",
connectionPointId: connectionPointId
}
});
logicalAddressId = logicalAddresss.data[0].id;
let serviceConsumers = await axios.get('http://api.ntjp.se/coop/api/v1/serviceConsumers.json', {
params: {
connectionPointId: connectionPointId,
logicalAddressId: logicalAddressId
}
});
consumer = serviceConsumers.data.filter(obj => {
return obj.hsaId === "SE2321000016-92V4"
});
serviceConsumerId = consumer[0].id;
let cooperations = await axios.get('http://api.ntjp.se/coop/api/v1/cooperations.json', {
params: {
connectionPointId: connectionPointId,
logicalAddressId: logicalAddressId,
serviceDomainId: serviceDomainId,
serviceConsumerId: serviceConsumerId,
include: "serviceContract"
}
});
var finalData = [];
cooperations.data.forEach(function(cooperation) {
axios.get('http://api.ntjp.se/coop/api/v1/serviceProducers.json', {
params: {
connectionPointId: connectionPointId,
logicalAddressId: logicalAddressId,
serviceDomainId: serviceDomainId,
serviceConsumerId: serviceConsumerId,
serviceContractId: cooperation.serviceContract.id
}
}).then(response => {
finalData.push({serviceContract: cooperation.serviceContract.namespace, serviceProducerDescription: response.data[0].description, serviceProducerHSAId: response.data[0].hsaId});
});
});
console.log(finalData);
}
</script>
</body>
我不太确定你的具体问题。但是假设你的意思是你有两个端点,第一个是 returns 一个对象数组(我们称之为 'getPeopleArray'
):
[
{
name: "John",
id: 1
},
{
name: "Anna",
id: 2
}
]
和第二个端点 returns 给定 id
的 gender
(让我们用一个参数 id
称它为 'getGender'
),.push
不会为您完成这项工作。
您的问题可以通过以下方式解决:
let peopleArray = [];
axios.get('api/' + 'getPeopleArray').then(people => {
peopleArray = people;
people.forEach((person, index) => {
axios.get('api/' + 'getGender?id='.concat(person.id.toString()))
.then(gender => {
peopleArray[index].gender = gender;
});
});
});
首先是您保存第一个请求的返回数组,然后您必须遍历该数组中的每个对象,使用 index
从第二个端点获取并分配它们的 genders
你的 [].forEach(callbackfn)
的论点。只要在所有请求完成期间或之前没有对 peopleArray
进行操作,索引就是正确的。
更新二:
为了回应您在评论 "why .push doesn't work?" 中提出的问题,我决定采用另一种方法如果您想使用 .push
结束您的算法并且不使用跟踪索引。
let peopleArray = [];
axios.get('api/' + 'getPeopleArray').then(people => {
people.forEach((person) => {
axios.get('api/' + 'getGender?id='.concat(person.id.toString()))
.then(gender => {
peopleArray.push({id: person.id, name: person.name, gender, gender});
});
});
});
这样,您只会在对象的性别也被提取时将其推送到您的集合 peopleArray
。这也将消除必须使用 .map
(如评论中建议的那样)来仅存储您希望保留的单个对象的属性,因为您在行 peopleArray.push({id: person.id, name: person.name, gender, gender});
.
我不喜欢阅读链式承诺,而是更喜欢使用 async/await
。您可以先获取您的列表,然后使用 map
遍历该列表并请求每个名称的性别。请记住,在继续之前,您必须等待 map
中的所有承诺都得到解决。
const axios = require('axios');
async function getPeople() {
let firstResult = await axios.get('api/path/endpoint1');
// firstResult = [{name: "John", id: 1}, {name: "Anna", id: 2}]
let updatedResult = firstResult.map(async item => {
let people = await axios.get('api/path/endpoint2' + item.name); // or however your endpoint is designed
// people = {name: "John", id: 1, gender: male}
item.gender = people.gender;
return item;
});
// updatedResult = undefined
Promise.all(updatedResult)
.then(finalResult => console.log(finalResult));
// [{name: "John", id: 1, gender: male}, {name: "Anna", id: 2, gender: female}]
}
您可以使用 async/awaits 并将 gender
密钥重新分配给第一个端点数据...
var users;
axios.get('api/' + endpoint1]).then(response => {
users = response; // assume all user id list
for(var idx in users) {
var data = async () => { return await axios.get('api/' + users[idx].id) } //get gender api by user id
users[idx].gender = data.gender; //create gender key value
}
console.log(users);
});