【问题标题】:Async call for computed property - Vue.js计算属性的异步调用 - Vue.js
【发布时间】:2018-06-13 15:35:03
【问题描述】:

我有一个计算属性,只有在存在属性匹配时才会使用它。因此,我正在调用以获取数据asynchronous,以便仅在需要时检索它。我在尝试调用 async 以返回计算属性的数据时遇到问题。

以下是我所拥有的:

new Vue({
    el: "#formCompleteContainer",
    data: {
        form: {},
        components: []
    },
    computed: {
        employeeList: function () {
            var self = this;
            if (_.some(this.components, function (component) {
                return component.ComponentInfo.Type === 8
            })) {
                var employees = [];
                $.ajax({
                    url: "/Form/GetAllUsers",
                    type: "GET"
                }).done(function (results) {
                    employees = results;
                });

                return employees;
            } else {
                return [];
            }
        }
    }
});

我知道这不起作用,因为我要在通话完成之前返回。我已经看到了如何使用 deferredobjects 以及什么没有,但我似乎无法弄清楚如何使用 Vue 来实现它。

【问题讨论】:

  • @DanielBeck 我决定不使用计算属性来做我想做的事情。但谢谢你的链接。我一定会检查一下,也许会在未来的项目中使用它。

标签: ajax vue.js


【解决方案1】:

对于您的用例,我认为计算属性不能实现目标。

我的解决方案:

  1. 创建一个数据属性作为一个“延迟”对象,
  2. 然后使用一个手表异步调用您的后端以获取新数据,最后分配给延迟对象

如下演示:

Vue.config.productionTip = false
app = new Vue({
  el: "#app",
  data: {
    product: "Boots",
    deferedProduct: ''
  },
  watch: {
    product: function (newVal, oldVal) {
      setTimeout(() => {
        this.deferedProduct = 'Cats in ' + newVal + '!'
      }, 1500)
    }
  },
  methods: {
    nextProduct: function () {
      this.product += 'a'
    }
  }
})
<script src="https://unpkg.com/vue@2.5.16/dist/vue.js"></script>
<div id="app">
  <button @click="nextProduct()">Click Me!</button>
    <h2>{{product}}</h2>
    <h2>{{deferedProduct}}</h2>
</div>

【讨论】:

    【解决方案2】:

    这就是vue-async-computed 的意义所在。它解决了您返回的承诺并处理任何竞争条件。

    new Vue({
        el: "#formCompleteContainer",
        data: {
            form: {},
            components: []
        },
        asyncComputed: {
            employeeList: function () {
                if (_.some(this.components, function (component) {
                    return component.ComponentInfo.Type === 8
                })) {
                    return $.ajax({
                        url: "/Form/GetAllUsers",
                        type: "GET"
                    });
                } else {
                    return Promise.resolve([]);
                }
            }
        }
    });
    

    【讨论】:

    • 完成这项工作远不需要第 3 方实施。
    【解决方案3】:

    在做了更多的研究之后,我走了另一条路。我同意 Sphinx 的观点,我认为我想要实现的目标不适用于计算属性。

    相反,我打算这样做:

    new Vue({
        el: "#formCompleteContainer",
        data: {
            form: {},
            components: [],
            employees: []
        },
        methods: {
            getEmployees: function () {
                var self = this;
                if (_.some(this.components, function (component) {
                   return component.ComponentInfo.Type === 8;
                })) {
                    $.ajax({
                        url: "/Form/Form/GetAllUsers",
                        type: "GET"
                    }).done(function (results) {
                        self.employees = results;
                    });
                }
            }
        },
        created: function () {
            this.form = pageModel.Form;
            this.components = pageModel.Components;
        },
        mounted: function () {
            this.getEmployees();
        }
    });
    

    【讨论】:

      【解决方案4】:

      正如已经指出的,mounted 和其他第 3 方解决方案可以工作。

      但是,将所需的 Promise 放入 data 属性中可以提高可读性和组件加载。然后使用 Vue 生命周期钩子 created,我们可以等待 Promise.then 解析。

      例如:

      requestService.js

      ...
         async foo(){
            let myRequest = someRequest.createInstance()
            await myRequest.onReady()
            return myRequest.getSomePromise()
         } 
      ...
      

      然后将import 服务放入你的组件中,同时声明一个data 属性:

      myComponent.vue

      ...
         data: (){
            myPromiseLoc: null,
         }
      ...
         created: (){
            requestService.foo().then( result =>
            {
               this.myPromiseLoc = result
            }
         }
      ...
      

      【讨论】:

      • 这只会在组件加载时执行一次请求。任务是仅在显示类型为 8 的组件时加载数据。
      • @Michael2 具体用例总是不同的。这个问题和实际问题与 async/await、promise 和生命周期挂钩有关。这个答案很好地概括了用户的实际问题。
      猜你喜欢
      • 2019-06-18
      • 1970-01-01
      • 2022-06-13
      • 2017-08-26
      • 1970-01-01
      • 2018-03-26
      • 2019-08-08
      • 2017-10-06
      • 2017-10-07
      相关资源
      最近更新 更多