开发者问题收集

找不到等待 vue.js 异步函数的方法

2017-09-03
23379

当我取消注释下面 fetchData 中的“return”时,以下代码可以正常工作。我该如何设置它以便等待 this.fetchData 完成以填充项目?我尝试了其他承诺、异步、等待的变体,但无法使其真正发挥作用……

到目前为止,我在 fetchData 中设置了一个 this.items ,但我意识到这绝对不是我真正想要做的。由于以这种方式设置,它显示了我调用的前 X 行,但在 fetchData 调用之后应该发生的所有代码都是错误的,从尝试执行 items.length 开始。

import axios from 'axios';

new Vue({
    el: '#app',
    data() {
        return {
            search: '',
            totalItems: 0,
            items: [],
            loading: true,
            pagination: {},
            headers: [ //some headers
            ],
            items: []
        }
    },
    watch: {
      pagination: {
        handler () {
          this.getDataFromApi()
            .then(data => {
              this.items = data.items
              this.totalItems = data.total
            })
        },
        deep: true
      }
    },
    mounted () {
      this.getDataFromApi()
        .then(data => {
          this.items = data.items
          this.totalItems = data.total
        })
    },
    methods: {
        fetchData() {
            axios.get('/api/v1/translations').then(response => {
                //console.log(response.data)
                this.items = response.data.data
            })

            //the return below is working 100%:
            //return [{id:1,key:1,lg:'en',text:'woopie'}];
        },

        getDataFromApi () {
            this.loading = true
            return new Promise((resolve, reject) => {
                const { sortBy, descending, page, rowsPerPage } = this.pagination

                let items = this.fetchData()
                const total = items.length

                //some code to setup pagination and sort

                setTimeout(() => {
                    this.loading = false
                    resolve({
                    items,
                    total
                    })
                    }, 1000)
            })
        }
    },
})
1个回答

更新后的答案

抱歉,在我下面的原始答案中,我完全忽略了这一点:

So far I set a this.items inside fetchData but I realize it's absolutely not what I want to actually do.

我的回答假定您 确实 想要 this.items 。对此我深表歉意。

若要从 fetchData 获取信息而不使用 this.items ,请使用 axios.get 中承诺上的 then 处理程序返回一个新的承诺(请记住, thencatch 返回承诺),该承诺通过 response.data.data 解析:

fetchData() {
//  vvvvvv------------------------
    return axios.get('/api/v1/translations').then(response => {
        return response.data.data;
//      ^^^^^^^^^^^^^^^^^^^^^^^^^
    })
},

这可以写得更简洁:

fetchData() {
    return axios.get('/api/v1/translations').then(response => response.data.data);
},

然后,在 getDataFromApi 中,对该承诺使用 then 处理程序:

getDataFromApi () {
    this.loading = true
    return this.fetchData().then(items => {
        // You might use this at some stage: const { sortBy, descending, page, rowsPerPage } = this.pagination
        this.loading = false;
        return { items, total: items.length };
    });
}

请注意, getDataFromApi 的消费者处理承诺拒绝(例如,使用 catch 处理程序)。如果您不希望消费者这样做,请不要返回承诺,而是在 getDataFromApi 中使用 catch


原始答案

axios.get 返回承诺:

fetchData() {
//  vvvvvv------------------------
    return axios.get('/api/v1/translations').then(response => {
        //console.log(response.data)
        this.items = response.data.data
    })
},

...然后使用它,而不是在 getFromApi 中创建一个新的承诺:

getDataFromApi () {
    this.loading = true
    return this.fetchData().then(() => {
        // You might use this at some stage: const { sortBy, descending, page, rowsPerPage } = this.pagination
        this.loading = false;
        return { items: this.items, total: this.items.length };
    });
}

请记住, then (和 catch )创建新的承诺;如果您 已经 有一个可以使用的承诺,则没有理由使用 new Promise 。有关该部分的更多信息: 什么是显式承诺构造反模式,我该如何避免它?

(请注意,我假设您出于某种原因想要在实例上使用 this.items 。如果没有,您只想使用 response.data 作为 axios.get...then 回调的返回值并在 getDataFromApi 中使用它。)

T.J. Crowder
2017-09-03