如何从 axios 响应对象中的所有项目中提取特定值到 vuex 状态
Posted
技术标签:
【中文标题】如何从 axios 响应对象中的所有项目中提取特定值到 vuex 状态【英文标题】:How can I extract specific values from all items in axios response object to a a vuex state 【发布时间】:2020-06-20 06:25:16 【问题描述】:这让我发疯了!
我有一个 axios 调用在控制台中返回一个 json 数组对象 - 检查!
>(100) […, …, …, …, …, …, …, …, …, …, …, …, …, …, …, …, …, …, …, …, …, …, …, …, …, …, …, …, …, …, …, …, …, …, …, …, …, …, …, …, …, …, …, …, …, …, …, …, …, …, …, …, …, …, …, …, …, …, …, …, …, …, …, …, …, …, …, …, …, …, …, …, …, …, …, …, …, …, …, …, …, …, …, …, …, …, …, …, …, …, …, …, …, …, …, …, …, …, …, …]
>0:
id: 54892250
iid: 1001
ref: "master"
sha: "63e3fc014e207dd4e708749cee3e89a1aa416b7d"
created_at: "2020-03-05T18:57:02.793Z"
updated_at: "2020-03-05T19:06:27.651Z"
>user: id: someuserid, name: "someuser", username: "someusername", state: "active", avatar_url: "https://assets.gitlab-static.net/uploads/-/system/user/avatar/4534925/avatar.png", …
>environment: id: 123456, name: "somename", slug: "somename-iw5iqp", external_url: "https://someaddress.com"
>deployable: id: someid, status: "success", stage: "deploy", name: "deploy-staging", ref: "master", …
status: "success"
__proto__: Object
>1: id: 54804365, iid: 1000, ref: "filter-out-expired-items", sha: "6225d8018c86fa906063aeea5c10c710ddced14c", created_at: "2020-03-05T12:25:18.949Z", …
>2: id: 54804175, iid: 999, ref: "master", sha: "aa5e50c50ba95e9b16cbc57fb968bf9075c625b2", created_at: "2020-03-05T12:24:02.284Z", …
>3: id: 54801934, iid: 998, ref: "filter-out-expired-items", sha: "4fc2
现在我需要对这个结果做两件事:
-
当完全展开时,这个响应很大——而且有数千个。而不是在 vuex 状态下存储 1000 个巨大的 json 响应 - 我想首先只提取我们关心的值,这些值如下:
身份证
参考
环境名称
状态
deployable.tag
类似于:
"id": id, "ref": ref, "environment": environment.name, "status": status, "tag": deployable.tag,
我该怎么做?
-
此响应在上面的许多页面上进行了分页,这只是一个页面结果的部分示例。
我有一个工作循环,我正在为所有这些循环获取 console.log。但我需要做的是在我提交状态之前连接所有页面(现在剥离到上述字段)。如果尝试过对象副本,推送到数组和各种有前途的实用程序 - 但我无法让它们中的任何一个工作:)
总之:
-
获取页面结果
将数组中的项目压缩为简化版本
将它们全部收集到我可以插入状态的对象中
循环的相关部分
// Use headers to get the number of pages
const pages = await axios.head(url, options)
.then((response) => response.headers['x-total-pages']);
console.log('pages=', pages); // DEBUG
// Loop through and push them to an array
for (let i = 0; i <= pages; i += 1)
console.log('i=', i);
options =
headers:
'Private-Token': token,
,
params:
order_by: 'created_at',
sort: 'desc',
per_page: 100,
page: i,
,
;
axios.get(url, options)
.then((result) => console.log(result.data); )
【问题讨论】:
你能贴出你的子数组(页面数组/列表)结构吗 这是我正在使用的 Gitlab 的 API - 他们有很好的文档和示例响应部署 api docs.gitlab.com/ee/api/… 他们的分页 docs.gitlab.com/ee/api/README.html#pagination 我正在努力制定我所知道的简洁的目标:) 但基本上它是一年多部署统计数据的总结。他们每年可以得到 3000-4000 个结果,这就是为什么我认为在将数据集放入状态之前对其进行拟合很重要 当您异步执行所有请求时,您将失去排序,并且您不会真正知道所有请求何时完成。当所有请求承诺都已解决时,您可以使用Promise.all()
。这就是你想要的吗?
【参考方案1】:
为总结果创建一个数组:
const results = [];
在您记录的位置,解析每个单独的结果:
result.data.forEach(item =>
results.push(
id: item.id,
ref: item.ref,
environment: item.environment.name,
status: item.status,
tag: item.deployable.tag
);
);
请注意,使用普通的for
循环而不是forEach
可能是一种性能优化。
【讨论】:
谢谢!这似乎工作得很好,是我在它之前尝试过的许多迭代之一。我一定是在做一些愚蠢的事情,然后将其丢弃为另一种方法,因为现在我用您的代码作为模板重试了它,它似乎工作得很好!我对你所说的 for 和 foreach 之间的性能很好奇 - 但这现在发生得非常快! 很好,没问题。 Google forEach vs for 循环,应该会有一些结果。 Here is a performance test 两年前,但在未知浏览器上。对于更大的数据集,这似乎无关紧要,甚至forEach
可以更快。【参考方案2】:
我认为您可以使用 Promise 来保持请求的顺序,从而跨页面数据排序。关键是将每个 axios 调用放入一个数组中,然后使用该数组调用 Promise.all([])
以按照您发出请求的原始顺序一次获得所有响应。
// Use headers to get the number of pages
const pages = await axios.head(url, options)
.then((response) => response.headers['x-total-pages']);
console.log('pages=', pages); // DEBUG
let promises = [];
// Loop through and push them to an array
for (let i = 0; i <= pages; i += 1)
console.log('i=', i);
options =
headers:
'Private-Token': token,
,
params:
order_by: 'created_at',
sort: 'desc',
per_page: 100,
page: i,
,
;
let promise = axios.get(url, options);
// this below keep responses order
promises.push(promise);
// This wait for all Axios calls to be resolved as promise
Promise.all(promises)
.then((result) =>
// now if you have 10 pages, you'll have result[0] to result[9], each of them is an axios response
console.log(result[0].data);
console.log(result[1].data); // if pages > 0
let items = []; // you can declare it outside too for Scope access
for (let i = 0; i <= pages; i += 1)
// so many records, then take the minimum info
if (result[i].data.length >= 1000)
result[i].data.forEach(item =>
items.push(
id: item.id,
ref: item.ref,
environment: item.environment.name,
status: item.status,
tag: item.deployable.tag
);
else
// Not so many records then take all info
items = items.concat(result[i]);
// TODO: do whatever you want with the items array now
);
【讨论】:
这不是我现在在工作解决方案中使用的东西,但我想花时间说声谢谢!它很好地介绍了我在通过 MVP 时正在考虑的一些事情:) 这很好。不客气。因为 axios 请求已经返回了一个 Promise,所以如果你想要一次将它们全部绑定在一起是很容易的。好好利用你的东西【参考方案3】:我会在这里使用Array.prototype.map
将原始对象映射为仅具有属性子集的简化对象:
const newResult = result.data.map(d => (
id: d.id,
ref: d.ref,
environmentName: d.environment.name,
status: d.deployable.status,
deployableTag: d.deployable.tag
))
const data = [
"created_at": "2016-08-11T07:36:40.222Z",
"updated_at": "2016-08-11T07:38:12.414Z",
"deployable":
"commit":
"author_email": "admin@example.com",
"author_name": "Administrator",
"created_at": "2016-08-11T09:36:01.000+02:00",
"id": "99d03678b90d914dbb1b109132516d71a4a03ea8",
"message": "Merge branch 'new-title' into 'master'\r\n\r\nUpdate README\r\n\r\n\r\n\r\nSee merge request !1",
"short_id": "99d03678",
"title": "Merge branch 'new-title' into 'master'\r"
,
"coverage": null,
"created_at": "2016-08-11T07:36:27.357Z",
"finished_at": "2016-08-11T07:36:39.851Z",
"id": 657,
"name": "deploy",
"ref": "master",
"runner": null,
"stage": "deploy",
"started_at": null,
"status": "success",
"tag": false,
"user":
"id": 1,
"name": "Administrator",
"username": "root",
"state": "active",
"avatar_url": "http://www.gravatar.com/avatar/e64c7d89f26bd1972efa854d13d7dd61?s=80&d=identicon",
"web_url": "http://gitlab.dev/root",
"created_at": "2015-12-21T13:14:24.077Z",
"bio": null,
"location": null,
"public_email": "",
"skype": "",
"linkedin": "",
"twitter": "",
"website_url": "",
"organization": ""
,
"pipeline":
"created_at": "2016-08-11T02:12:10.222Z",
"id": 36,
"ref": "master",
"sha": "99d03678b90d914dbb1b109132516d71a4a03ea8",
"status": "success",
"updated_at": "2016-08-11T02:12:10.222Z",
"web_url": "http://gitlab.dev/root/project/pipelines/12"
,
"environment":
"external_url": "https://about.gitlab.com",
"id": 9,
"name": "production"
,
"id": 41,
"iid": 1,
"ref": "master",
"sha": "99d03678b90d914dbb1b109132516d71a4a03ea8",
"user":
"avatar_url": "http://www.gravatar.com/avatar/e64c7d89f26bd1972efa854d13d7dd61?s=80&d=identicon",
"id": 1,
"name": "Administrator",
"state": "active",
"username": "root",
"web_url": "http://localhost:3000/root"
,
"created_at": "2016-08-11T11:32:35.444Z",
"updated_at": "2016-08-11T11:34:01.123Z",
"deployable":
"commit":
"author_email": "admin@example.com",
"author_name": "Administrator",
"created_at": "2016-08-11T13:28:26.000+02:00",
"id": "a91957a858320c0e17f3a0eca7cfacbff50ea29a",
"message": "Merge branch 'rename-readme' into 'master'\r\n\r\nRename README\r\n\r\n\r\n\r\nSee merge request !2",
"short_id": "a91957a8",
"title": "Merge branch 'rename-readme' into 'master'\r"
,
"coverage": null,
"created_at": "2016-08-11T11:32:24.456Z",
"finished_at": "2016-08-11T11:32:35.145Z",
"id": 664,
"name": "deploy",
"ref": "master",
"runner": null,
"stage": "deploy",
"started_at": null,
"status": "success",
"tag": false,
"user":
"id": 1,
"name": "Administrator",
"username": "root",
"state": "active",
"avatar_url": "http://www.gravatar.com/avatar/e64c7d89f26bd1972efa854d13d7dd61?s=80&d=identicon",
"web_url": "http://gitlab.dev/root",
"created_at": "2015-12-21T13:14:24.077Z",
"bio": null,
"location": null,
"public_email": "",
"skype": "",
"linkedin": "",
"twitter": "",
"website_url": "",
"organization": ""
,
"pipeline":
"created_at": "2016-08-11T07:43:52.143Z",
"id": 37,
"ref": "master",
"sha": "a91957a858320c0e17f3a0eca7cfacbff50ea29a",
"status": "success",
"updated_at": "2016-08-11T07:43:52.143Z",
"web_url": "http://gitlab.dev/root/project/pipelines/13"
,
"environment":
"external_url": "https://about.gitlab.com",
"id": 9,
"name": "production"
,
"id": 42,
"iid": 2,
"ref": "master",
"sha": "a91957a858320c0e17f3a0eca7cfacbff50ea29a",
"user":
"avatar_url": "http://www.gravatar.com/avatar/e64c7d89f26bd1972efa854d13d7dd61?s=80&d=identicon",
"id": 1,
"name": "Administrator",
"state": "active",
"username": "root",
"web_url": "http://localhost:3000/root"
]
const result = data.map(d => (
id: d.id,
ref: d.ref,
environmentName: d.environment.name,
status: d.deployable.status,
deployableTag: d.deployable.tag
))
console.log(result)
【讨论】:
以上是关于如何从 axios 响应对象中的所有项目中提取特定值到 vuex 状态的主要内容,如果未能解决你的问题,请参考以下文章
如何使用 Express 和 Axios 从我的 get 请求发送响应对象到前端?
如何在 Vue 和 Axios 中循环访问 API 端点 JSON 对象?
如何从 JMeter 的 json 响应中的长 html 内容中提取特定的 *token* 值
如何从我得到的数组中获取特定的数组元素作为调用 axios.get() 调用的函数的响应 [重复]
Vue.js:如何将特定对象中的布尔字段从 false 更改为 true @click 处于突变状态和带有动作 axios 的服务器?