Thursday, 1 October 2020

How to fix memory leak in my vue.js / axios app?

I have a single page which displays a list of rows from a table using an inline vue.js script, it fetches the list of rows on page load, but also fetches the table again when pusher events are received.

I have a modal window that opens and allows the user to add new people to the table. When the user presses submit (on the form) the modal posts an ajax request (using axios) to submit the record. This sends a App\Events\NewQueueMember event to Pusher which my vue app also listens for and when this occurs the updateData method is called to refresh the table.

The problem I have is when the form is submitted, the page because somewhat unresponsive for about 5 seconds before then being able to scroll on the page again. Looking at Chromes Task manager I can see the RAM usage for the tab doubles and the CPU usage is considerably high too.

I believe its some sort of memory leak but I'm not sure how to resolve and would appreciate some guidance.

This is the form that resides within my modal.

@csrf Customer Name Name will be displayed internally and to the customer
<div class="form-group">
    <label for="add-person-mobile">Mobile Number</label>
    <input type="phone" class="form-control" name="phone_number" id="add-person-mobile"
           v-model="addPersonForm.phone_number">
    <small id="emailHelp" class="form-text text-muted">Please ensure number starts with +44 </small>
</div>

<div class="form-group">
    <label for="add-person-party-size">Party Size</label>
    <input type="number" class="form-control" name="party_size" id="add-person-party-size"
           v-model="addPersonForm.party_size">
</div>

This is the vue.js script block that sites within the same page

<script>

    Vue.use(VueTimeago, {
        name: 'Timeago',
    })

    let vm = new Vue({
        el: '#app',

        data() {
            return {
                live_count: null,
                queue: null,
                loading: true,
                errored: false,
                buttons: {
                    add_to_queue_label: 'Add to Queue',
                    add_to_queue_disabled: false
                },
                addPersonForm: {
                    name: '',
                    phone_number: '',
                    party_size: ''
                }
            }
        },

        mounted() {
            axios
                .get(`/business/queue-live-feed`)
                .then(response => {
                    console.log('got response data')
                    console.log(response.data)
                    this.queue = response.data.queue
                    this.live_count = response.data.live_count
                })
                .catch(error => {
                    console.log(error)
                    this.errored = true
                })
                .finally(() => this.loading = false);
        },
        
        methods: {
            updateData: function () {
                axios.get(`/business/queue-live-feed`)
                    .then(response => {
                        this.queue = response.data.queue
                        this.live_count = response.data.live_count
                    })
                    .catch(error => {
                        console.log(error)
                        this.errored = true
                    });
            },

            addPerson: function (event) {
                console.log('calling resource...');
                this.buttons.add_to_queue_disabled = true;
                this.buttons.add_to_queue_label = "Adding...";

                axios.post(`/business/queue/add2`, this.$data.addPersonForm)
                    .then(response => {
                        console.log('got a response!');
                        console.log(response.data);
                        // this.updateData(); <- when I comment this line, the unresponsiveness lasts around 5-10 seconds.
                    })
                    .catch(error => {
                        console.log('some error happened :(')
                        this.buttons.add_to_queue_disabled = true;
                        this.buttons.add_to_queue_label = "Retry";
                        // $('#manual-add-people').modal('hide');
                        // console.log(error)
                    })
                    .finally(() => {
                        console.log('finished method');
                        this.buttons.add_to_queue_disabled = false;
                        this.buttons.add_to_queue_label = "Add to Queue";
                        $('#manual-add-people').modal('hide');
                    });

                this.addPersonForm = {};
            },

        }
    })


    // PUSHER CODE
    Pusher.logToConsole = true;

    const pusher = new Pusher('', {
        cluster: '',
        authEndpoint: '/broadcasting/auth',
        auth: {
            headers: {
                'X-CSRF-TOKEN': '',
            }
        }
    });

    pusher.subscribe(`private-queue.business.`)
        .bind('App\\Events\\NewQueueMember', (data) => {
            vm.updateData()
        })
        .bind('App\\Events\\QueueMemberKicked', (data) => {
            vm.updateData()
        })
        .bind('App\\Events\\QueueMemberLeft', (data) => {
            vm.updateData()
        })
        .bind('App\\Events\\QueueMemberNoShow', (data) => {
            vm.updateData()
        })
    ;

</script>

The method in question is the addPerson which is called when the form is submitted.

I believe the issue is related to my usage of this.$data.addPersonForm, if I switch this to an empty array.

EDIT: This is a sample response that comes back from my /business/queue/add2 endpoint.

{guest_id: 55, queue_lane_id: 1, party_size: 2, short_id: "RIS0MRk0",…}
business: {id: 2, name: "Acme Ltd", business_type_id: 2, is_active: 1,…}
business_id: 2
created_at: "2020-09-27T23:53:11.000000Z"
customer: null
guest: {id: 55, name: "AJAX Test 29", phone_number: "+1234567890", business_id: 2,…}
guest_id: 55
id: 79
party_size: 2
queue_entry_time: "2020-09-28 00:53:11"
queue_lane_id: 1
short_id: "RIS0MRk0"
updated_at: "2020-09-27T23:53:11.000000Z"

It's just a JSON blob with details of the record they just created, its not really huge either.

I have also updated the Vue script above to reflect the additional method call I made in my then() function under addPerson.



from How to fix memory leak in my vue.js / axios app?

No comments:

Post a Comment