Search code examples
vue.jsasync-awaitvuejs2vuex

Vue.js Non-blocking while statement (polling backend until progress is finished)


Inside a vue action, I want to poll my backend (call another async action like described below? ) until the something has finished processing (frontend shows a loader until progress is over).

In other words, I want to repeatedly make an API call looking like :

actions: {
    load: async ({dispatch, commit, state}, {args}) => {
    await dispatch('progressPolling', {progressUrl, userId})
    // continue ONLY when progress has finished, else blocks at this statement
    ...
    }

    progressPolling: async ({dispatch, commit}, {progressUrl, userId}) => {
        var finished = false
        while(!finished) : {
            var progress = await dispatch('getResource', {url: progressUrl, userId: userId})
            finished = (progress.data.finished === true)
            // timeout of 2 secs
         }
    }
...
}

My understanding is that that you can use the setTimeout() statement to wait between calls, but am not sure how to turn this into a non-blocking while statement, or simply what is the best practice to achieve this.

EDIT: "Non-blocking" because I was originally using a wait() statement in a while loop. That made the UI freeze each time it had to wait.


Solution

  • I would use recursive function to do this.

    progressPolling: async ({dispatch, commit}, {progressUrl, userId}) => {
        // Define a recursive function
        async function getResource (resolve) {
            const progress = await dispatch('getResource', {url: progressUrl, userId: userId})
            // Recurse when not finished
            if (progress.data.finished !== true) {
                setTimeout( () => getResource(resolve), 2000);
            } 
        }
        // Kick the recursive function
        return new Promise (resolve => getResource(resolve))
        // Finished!
    }