Vue.js技术问题:Promise结果添加至数组时出现重复数据异常
解决Vue组件中
purchaseDatePrice重复及属性更新不生效的问题 问题根源分析
你遇到的两个核心问题:
- 重复对象:确实是
this.cryptoLocalStorage.push({ purchaseDatePrice: values});导致的——每次异步请求完成后,你都往数组里新增了一个只包含purchaseDatePrice的对象,这完全没必要。 - 移除push后更新不生效:有两个关键原因:
- 循环中的闭包陷阱:for循环里的
i是共享变量,当异步Promise的then回调执行时,循环已经结束,i的值已经变成了数组的长度,此时修改this.cryptoLocalStorage[i]其实操作的是不存在的元素。 - 响应式追踪问题:从
cryptostorage.fetch()获取的对象是普通JS对象,Vue默认不会对这类对象的新增属性进行响应式监听,直接赋值purchaseDatePrice后,Vue无法检测到变化,所以$data里看不到更新。
- 循环中的闭包陷阱:for循环里的
修复后的代码
推荐用async/await结合数组map来处理异步请求,既避免闭包问题,又能确保响应式更新:
<template> <div> <pre>{{ $data }}</pre> </div> </template> <script> import { getPrice, getPriceForTimestamp } from '../api/crypto'; import { cryptostorage } from '../api/utils'; export default { name: 'test', data () { return { cryptoLocalStorage: cryptostorage.fetch() } }, methods: { async getPriceForAmount() { // 先收集所有异步请求Promise,同时关联对应的数组元素 const pricePromises = this.cryptoLocalStorage.map(item => { return getPriceForTimestamp(item.title, item.date) .then(price => ({ item, price })); // 把元素和对应的价格绑定 }); try { // 等待所有请求完成 const results = await Promise.all(pricePromises); // 遍历结果,给每个元素添加响应式属性 results.forEach(({ item, price }) => { // 使用this.$set确保新增属性被Vue响应式追踪 this.$set(item, 'purchaseDatePrice', price); }); } catch (e) { console.error(e); } } }, created() { this.getPriceForAmount(); } } </script>
关键优化点
- 避免闭包陷阱:用
map遍历数组,每个迭代的item都是独立的变量,异步回调执行时能正确关联到对应的数组元素。 - 响应式更新:通过
this.$set(item, 'purchaseDatePrice', price)给对象新增属性,Vue会自动为这个属性添加响应式监听,确保视图和$data同步更新。 - 批量处理异步请求:用
Promise.all一次性等待所有请求完成,比循环中逐个处理更高效,也避免了多次触发数组更新。
如果不想用async/await,也可以用Promise.all的链式调用写法:
getPriceForAmount() { const pricePromises = this.cryptoLocalStorage.map(item => getPriceForTimestamp(item.title, item.date).then(price => ({ item, price })) ); Promise.all(pricePromises) .then(results => { results.forEach(({ item, price }) => { this.$set(item, 'purchaseDatePrice', price); }); }) .catch(e => console.error(e)); }
修复后的预期结果
你的$data会变成:
{ "cryptoLocalStorage": [ { "id": 0, "title": "ETH", "amount": "0.5", "date": "2018-01-16T12:39:00.000Z", "purchaseDatePrice": 1050.26 }, { "id": 1, "title": "BTC", "amount": "1", "date": "2018-01-09T12:42:00.000Z", "purchaseDatePrice": 14468.5 }, { "id": 2, "title": "LTC", "amount": "0.003", "date": "2017-11-14T12:48:00.000Z", "purchaseDatePrice": 62.13 } ] }
内容的提问来源于stack exchange,提问作者mrks
相关产品推荐
相关产品推荐

