简体   繁体   中英

JavaScript: Promise on recursion

I got something like this:

    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;  
        }

    },

Alright - this is some JavaScript using Vue.js and vue-resource to do am API call (process). The API returns the number of elements to be processed. If this number is > 0, the function should be executed again. This works fine.

Now I would like to solve the following:

Executing the run function should set this.busy = true . After the function process is done processing all items, this.busy should be set to false .

So I read something about promises - but I still don't get how I could use them in this case.

You would need to:

  • return the promise (both in process as in the then callback)
  • use arrow functions when you want to have access to the same this value.

Suggested code:

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);  
    }
},

It should be noted however that introducing the busy flag should not be necessary when you stick to the promise pattern. It should certainly not be used to somehow wait for the process to complete. For that purpose you should stick to the then callback system (or use the async/await syntax, which comes down to the same thing).

Use deferred:

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
                }
        );  

    }

},

I do it without test.

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM