【问题标题】:JavaScript: Promise on recursionJavaScript:对递归的承诺
【发布时间】:2017-09-07 18:56:54
【问题描述】:

我得到了这样的东西:

    methods: {
        process: function process(id) {
            this.$http.post('controller/process', { id: id }).then(function (res) {
                if (res.data.items > 0) {
                    this.process(id);
                } else { 
                    return true;
                }
            }, function (data) {
                this.$notify(data, 'danger');
                this.progress = false;
            });
        },
        run: function run($id) {
            this.busy = true;   
            this.process($id);  
            this.busy = false;  
        }

    },

好的 - 这是一些使用 Vue.js 和 vue-resource 进行 API 调用(进程)的 JavaScript。 API 返回要处理的元素数量。如果此数字 > 0,则应再次执行该函数。这很好用。

现在我想解决以下问题:

执行run函数应该设置this.busy = true。函数process处理完所有项目后,this.busy应设置为false

所以我读了一些关于 Promise 的文章——但我仍然不明白在这种情况下如何使用它们。

【问题讨论】:

  • 如果您从该函数返回承诺,您可以在递归函数返回 then 语句后执行您的代码。例如YourClass.process(id).then(result => doSomethingWith(result))。如果你这样做,你就不需要使用忙标志。
  • 既然process函数是一个promise,那么你可以做this.process($id).then(function() { this.busy = false; } );

标签: javascript promise vue.js


【解决方案1】:

您需要:

  • 返回承诺(processthen 回调)
  • 当您想要访问相同的this 值时,请使用箭头函数。

建议代码:

methods: {
    process: function process(id) {
        return this.$http.post('controller/process', { id: id }).then((res) => {
            if (res.data.items > 0) {
                return this.process(id);
            }
        }, (data) => {
            this.$notify(data, 'danger');
            this.progress = false;
        });
    },
    run: function run($id) {
        this.busy = true;
        this.process($id).then( _ => this.busy = false);  
    }
},

但是应该注意的是,当您坚持承诺模式时,不需要引入 busy 标志。它当然不应该用于以某种方式等待该过程完成。为此,您应该坚持使用then 回调系统(或使用async/await 语法,这归结为同一件事)。

【讨论】:

    【解决方案2】:

    使用延迟:

    methods: {
        process: function process(id) {
            var deferred = $q.defer();
            this.$http.post('controller/process', { id: id }).then(function (res) {
                if (res.data.items > 0) {
                    this.process(id);
                } else { 
                    return deferred.resolve(true);
                }
            }, function (data) {
                this.$notify(data, 'danger');
                this.progress = false;
                return deferred.resolve(true); //if not will fail promise
            });
    
            return deferred.promise;
        },
        run: function run($id) {
    
            this.busy = true;   
            this.process($id)
                .then(
                    function() { //executes when resolve
                        this.busy = false;  
                    },
                    function() {
                        //executes when you run deferred.reject() in process method
                    }
            );  
    
        }
    
    },
    

    我没有测试就这样做了。

    【讨论】:

    • 您正在介绍deferred anitpattern。为避免这种情况,应返回承诺本身,如其他 cmets 和我回答的内容所示。
    • 我不知道是什么问题,我只是在解释如何开始解决他们的问题。如果他以后想重构以做出良好的实践代码,将不胜感激。他要求更好的解决方案,回答问题,所有人都会学习。
    猜你喜欢
    • 2015-05-15
    • 1970-01-01
    • 2017-12-18
    • 2014-02-04
    • 1970-01-01
    • 2015-12-05
    • 1970-01-01
    • 2018-05-29
    • 1970-01-01
    相关资源
    最近更新 更多