Update a watched list only after all commits

Hi,

I’m having a problem with multiple mutations. My problem works like this:
I’m executing an operation over a list of projects where I have to update multiple task dates (start, end) for each project. So, I created an action where I dispatch the list of projects with its correspondent tasks

this.projects.forEach(project => {
  this.$store.dispatch(
    'shiftTaskDates', {
      project,
      tasks: project.tasks,
      daysToShift
    });
});

The dispatch action works like this

shiftTaskDates({ getters: g, commit }, { project, tasks, daysToShift }) {
  const projectChanges = [];

  tasks.forEach(task => {
    const taskChanges = [];
    const result = g.moveTask(phase, daysToShift, project.id);

    if (result) {
      result.project = project;
      result.duration = phase.duration;
      taskChanges.push(result);
    }

    projectChanges.push({ project, taskChanges });
  });

  commit(SHIFT_TASKS_MUTATION, projectChanges);
},

The result receives an object with task, newStart and newEnd

The shift mutation works like this:

[SHIFT_TASKS_MUTATION](s, projectChanges) {
  projectChanges.forEach(({ project, taskChanges }) => {
    taskChanges.forEach(({ task, start, end}) => {
      task.start = start;
      task.end = end;
    }));
  });
},

Now here is the problem:
On the projects page, I have a watcher that check for changes inside the projects list, like this:


import { mapState } from 'vuex';
export default {
  data() {
    return {
      // attributes
    }
  },
  computed: {
    ...mapState(['projects'])
  },
  watch: {
    projects() {
      // update operations
    }
  }
}

Every time a task mutate, the projects list is also updated, witch triggers the watcher and makes all updates that needs to be done for one task, witch makes the application very slow for a simple batch of changes inside the list. Something like ~15s for a list with 200 tasks.

Is there a way to get the updated list only after all commits?

I tried to put something similar together in JSFiddle:

https://jsfiddle.net/skirtle/x8dtbfwk/

From that I have two observations:

  1. I don’t see why your watch handler would be called at all. Mutating a task will not trigger a watch on projects.
  2. Even if I use deep: true, it will only call the watcher once. Watchers are batched to run just before rendering, so all the commits should happen prior to the watch handler being called. If the action was doing something asynchronous it could split them up but I don’t see anything like that in your code.

So how are you determining that the watch handler is being called once per task? Console logging in the handler?

With all those nested loops I wouldn’t be surprised if the problem lies elsewhere.