Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Are watches asynchronous?

I watch a variable radioStatus in a Vue instance:

watch: {
    radioStatus: function(val) {
      if (!this.discovery) {
        $.ajax({ url: '/switch/api/radio/' + (val ? 'on' : 'off') })
      }
    }

It may be modified in an AJAX call triggered upon page reload:

$.ajax({
  url: "/api",
  cache: false
})
  .done(function(response) {
    vm.discovery = true;
    vm.radioStatus = response.radio.ison;  // <-- the change I mention below is here
    vm.discovery = false;
  });

Can I assume that all of the method triggered by a radioStatus change will be completed before going to the next line (namely vm.discovery = false)?

My concern is with the fact that vm.discovery is a flag used by several watched variables (in the same way as radioStatus) and that it will flip before the functions of the watched variables are finished.

like image 353
WoJ Avatar asked Oct 29 '16 17:10

WoJ


1 Answers

Yes, watchers are asynchronous. Ref: https://vuejs.org/guide/computed.html#Watchers

Quoted from above link:

Watchers

While computed properties are... This is most useful when you want to perform asynchronous or expensive operations in response to changing data.

In your case above, the vm.discovery = false; will be completed before going into watch. If you are setting vm.discovery to false, then your ajax call inside radioStatus will always get executed.

To avoid that, you may try vm.$nextTick() as follows:

$.ajax({url: "/api", cache: false})
    .done(function(response) {
        vm.discovery = true;
        vm.radioStatus = response.radio.ison;
        vm.$nextTick( () => {
            console.log("Setting vm.discovery to false");
            vm.discovery = false;
        });
    });

It is again a tricky thing to do - because your radioStatus() callback in watch is also going to happen in the nextTick only. But assuming watch is triggered by the previous line itself (vm.radioStatus = ...), technically it should go into the queue first, and therefore get completed earlier. You will have to confirm with a series of console.log statements.

like image 150
Mani Avatar answered Oct 18 '22 09:10

Mani