Problems with non-Synchronize updates on Vue watcher

problem description

In

Vue, if wather is not updated by Synchronize, it will be put in a queue and will be updated after the end of the same event loop. The relevant code is in the queueWatcher method of scheduler.
this deals with a scenario:
wather is triggered when the queue is being updated.

  if (!flushing) {
      queue.push(watcher)
    } else {
      let i = queue.length - 1
      while (i > index && queue[i].id > watcher.id) {
        i--
      }
      queue.splice(i + 1, 0, watcher)
    }
  }

I don"t understand why we have to deal with it this way. Can"t you push directly to the end?
what are the benefits of such a design now?

append description. The code
vue is not in the same time cycle. If the wather, is not executed and the wather is triggered again, it will only be executed once.

     queue.splice(i + 1, 0, watcher)

this side knows the index, before this wather and issues the second touch behind this. Still execute update twice. Since they are all executed twice, why not push directly to the last

Jul.09,2021

think about what happens when you constantly modify data in a function


first, go back to the update function. computed triggers the dependency dep.notify () , that is, subs [I] .update () , that is, queueWatcher

.
  update () {
    /* istanbul ignore else */
    if (this.computed) {
      // A computed property watcher has two modes: lazy and activated.
      // It initializes as lazy by default, and only becomes activated when
      // it is depended on by at least one subscriber, which is typically
      // another computed property or a component's render function.
      if (this.dep.subs.length === 0) {
        // In lazy mode, we don't want to perform computations until necessary,
        // so we simply mark the watcher as dirty. The actual computation is
        // performed just-in-time in this.evaluate() when the computed property
        // is accessed.
        this.dirty = true
      } else {
        // In activated mode, we want to proactively perform the computation
        // but only notify our subscribers when the value has indeed changed.
        this.getAndInvoke(() => {
          this.dep.notify()
        })
      }
    } else if (this.sync) {
      this.run()
    } else {
      queueWatcher(this)
    }
  }

so when you update, there will also be Watcher triggered by computed , so you can't directly push , otherwise the order will be out of order.


answer your own questions. In fact, it is very simple to make this question clear. The reason why it is cached in a queue is to avoid unnecessary updates. For example,

data: {
    a: 1
},
computed: {
    b: function(){
        this.a + 1
    }
}

methods: {
    act: function(){
        this.a = 2;
        // do someting
        this.a = 1
    }
}

in the act operation, we change a first and then change it back. Ideally, a does not change, and b does not recalculate. In fact, if you think about it, you will know that it is impossible to do so. Because as long as a changes the wather of b, it is already in the update queue. All we can avoid is that b has changed other calculations.
this requires that the wather of b get the latest value of a when it executes update. This is 1.
back to the question, if the watehr of an in the queue has been updated, then the wather of the latter a should be placed after the currently updated wather and updated immediately. This ensures that the following wather can get the latest value when an is used.
similarly, if the wather of a has not been updated, then the wather of the new a will be placed next to the wather of the previous a, in order to ensure that the following wather can get the latest value

when an is used.
Menu