You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

Vue.js技术问题:Promise结果添加至数组时出现重复数据异常

解决Vue组件中purchaseDatePrice重复及属性更新不生效的问题

问题根源分析

你遇到的两个核心问题:

  1. 重复对象:确实是this.cryptoLocalStorage.push({ purchaseDatePrice: values});导致的——每次异步请求完成后,你都往数组里新增了一个只包含purchaseDatePrice的对象,这完全没必要。
  2. 移除push后更新不生效:有两个关键原因:
    • 循环中的闭包陷阱:for循环里的i是共享变量,当异步Promise的then回调执行时,循环已经结束,i的值已经变成了数组的长度,此时修改this.cryptoLocalStorage[i]其实操作的是不存在的元素。
    • 响应式追踪问题:从cryptostorage.fetch()获取的对象是普通JS对象,Vue默认不会对这类对象的新增属性进行响应式监听,直接赋值purchaseDatePrice后,Vue无法检测到变化,所以$data里看不到更新。

修复后的代码

推荐用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>

关键优化点

  1. 避免闭包陷阱:用map遍历数组,每个迭代的item都是独立的变量,异步回调执行时能正确关联到对应的数组元素。
  2. 响应式更新:通过this.$set(item, 'purchaseDatePrice', price)给对象新增属性,Vue会自动为这个属性添加响应式监听,确保视图和$data同步更新。
  3. 批量处理异步请求:用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

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.05.15 03:49:02