Skip to main content

Parallele Vuex-Dispatches – warum sie zum Problem werden können

In modernen Vuex-Anwendungen werden State-Änderungen über Actions gestartet. Dadurch lassen sich komplexe Abläufe elegant kapseln, doch in der Praxis kann es dabei leicht zu mehrfachen Action-Dispatches kommen – etwa durch doppelte Klicks oder parallele Aufrufe aus verschiedenen Komponenten.

Das Ergebnis:

  • doppelte Netzwerkaufrufe
  • unnötige Serverlast
  • inkonsistente States
  • und schwer nachvollziehbare Logs

Gerade in größeren Projekten oder Enterprise-Anwendungen führt das zu instabilem Verhalten, unnötigem Debugging-Aufwand und Performance-Verlust.

Unser Ziel war klar: stabile Zustände, weniger Nebenwirkungen und dadurch mehr Kontrolle über asynchrone Prozesse.

Unsere Lösung: das Vuex-Mutex-Plugin

Um wiederholte oder parallele Action-Dispatches zuverlässig zu verhindern, haben wir bei IITS Consulting das Open-Source-Plugin Vuex-Mutex entwickelt.
Es handelt sich um einen intelligenten Mechanismus, der doppelte oder gleichzeitig gestartete Vuex-Aktionen automatisch erkennt und steuert.

Das Plugin koordiniert parallele Actions und entscheidet, wie mit weiteren Aufrufen umgegangen wird – sie können geteilt, blockiert oder verworfen werden, je nach Konfiguration.
So erhält jede Vuex-Action ihren eigenen „Mutex“ (gegenseitigen Ausschluss).

Das Ergebnis: mehr Stabilität, weniger Nebenwirkungen und ein konsistenter Application-State – besonders bei asynchronen Prozessen wie API-Requests, Formular-Submits oder automatischen Refresh-Zyklen.

Die wichtigsten Eigenschaften im Überblick:

  • Deduplizierung laufender Aktionen („in-flight“)
  • Verhinderung schneller Wiederholungen („quick repeats“)
  • Flexible Filterung über include / exclude-Regeln
  • Feinsteuerung über verschiedene Modi: share, drop, block, warn
  • Vollständig TypeScript-fähig und kompatibel mit Vuex 3 & 4

Warum überhaupt noch Vuex?

Man könnte sich fragen, warum wir 2025 überhaupt noch ein Plugin für Vuex entwickeln – schließlich gilt Pinia inzwischen als offizieller Nachfolger im Vue-Ökosystem.
Doch Vuex ist alles andere als verschwunden: Laut npm wird es (Stand Oktober 2025) weiterhin über 1,4 Millionen Mal pro Woche heruntergeladen, während Pinia bei rund 2,3 Millionen Downloads liegt.

Viele Enterprise- und Kundenprojekte basieren nach wie vor auf Vue 2 oder Vue 3 mit Vuex. Diese Systeme laufen stabil, sind tief integriert und lassen sich nicht ohne Weiteres auf Pinia migrieren, ohne funktionale Risiken oder hohen Entwicklungsaufwand in Kauf zu nehmen.
Gerade in großen Codebasen gilt oft der pragmatische Ansatz: Stabilisieren statt Umschreiben.

Deshalb wurde das Vuex-Mutex-Plugin entwickelt – als robuste Ergänzung für bestehende Projekte, die weiterhin Vuex einsetzen, aber mehr Kontrolle und Zuverlässigkeit bei parallelen Actions benötigen.

Wichtig:
Die Architektur des Plugins ist bewusst so entworfen, dass sich die Mutex- und Deduplizierungslogik leicht auf Pinia übertragen lässt.
Das bedeutet: Wer langfristig migrieren möchte, kann diese Konzepte praktisch unverändert übernehmen – nur die Integrationsebene ändert sich.

Codebeispiel & Integration

Installation

npm i @iits-consulting/vuex-mutex

oder

yarn add @iits-consulting/vuex-mutex

Einbindung im Store

import { createStore } from 'vuex'
import { createVuexMutexPlugin } from '@iits-consulting/vuex-mutex'

export const store = createStore({
  // ...state, mutations, actions, modules
  plugins: [
    createVuexMutexPlugin({
      // Überwache nur bestimmte Actions/Namespaces (Regex)
      include: [/^user\//, /^tasks\//],
      // Optional: bestimmte Actions explizit ausschließen
      // exclude: [/^debug\//],

      // Dedupe-Strategie
      dedupe: {
        // Wenn identische Action bereits läuft:
        // 'share' = Promise teilen, 'drop' = verwerfen,
        // 'block' = hart blocken/Fehler, 'warn' = nur warnen
        inFlight: 'share',

        // Wenn kurz nach Abschluss erneut ausgelöst:
        quickRepeat: 'drop',
        // Zeitfenster für „kurz danach“ in ms
        thresholdMillis: 500
      },

      // Debug-Logs aktivieren/deaktivieren
      debug: false,

      // Optional für Logging/Optimierungen
      isProduction: process.env.NODE_ENV === 'production',
    }),
  ],
})

Typischer Anwendungsfall (API-Action)

// user/actions.ts
export const actions = {
  async fetchProfile({ commit }, userId: string) {
    const res = await fetch(`/api/users/${userId}`)
    const data = await res.json()
    commit('setProfile', data)
    return data
  }
}

Was das Plugin hier tut:

  • Doppelklick/Mehrfach-Dispatch von user/fetchProfile während der erste Request läuft → wird geteilt (inFlight: ‘share’), es entsteht kein zweiter Request
  • Derselbe Dispatch kurz nach Abschluss (≤ 500 ms) → wird verworfen (quickRepeat: ‘drop’)
  • Ergebnis: weniger Last, keine Doppel-Logs, konsistenter State

Empfohlene Profile

  • API-Calls: inFlight: ‘share’, quickRepeat: ‘drop’, thresholdMillis: 300–700
  • Form-Submit/Transaktionen: inFlight: ‘block’, quickRepeat: ‘block’ (verhindert konsequent Mehrfach-Ausführungen)
  • Entwicklung/Debug: debug: true (zeigt Matches und Aktionen im Console-Log)

Eckfälle

  • Payload-Identität: Dedupe wirkt nur bei identischem Payload. Wenn du z. B. Timestamps mitgibst, sind Aufrufe nie „gleich“
  • Reentranz: Actions, die intern weitere Actions dispatchen, werden korrekt erkannt (kein Deadlock)

Technische Details & Interna

Unter der Haube nutzt das Plugin eine interne Map, um aktive Aktionen anhand eines eindeutigen Schlüssels zu identifizieren.
Dieser Schlüssel wird aus Namespace, Action-Name und einer stabil serialisierten Payload gebildet, wodurch das Plugin exakt bestimmen kann, ob zwei Dispatches tatsächlich identisch sind.

Re-Entrant Dispatches – also Aktionen, die sich selbst indirekt erneut aufrufen – erkennt das Plugin automatisch, um Deadlocks zu vermeiden.
Der interne Zustand des Plugins (aktive oder zuletzt ausgeführte Actions) wird für jede Store-Instanz separat verwaltet und beim Neuaufbau des Stores automatisch zurückgesetzt. Dadurch ist sichergestellt, dass keine alten Mutex-Daten aus vorherigen Sitzungen übernommen werden.

Für Debug-Zwecke lässt sich mit debug: true eine detaillierte Logausgabe aktivieren, die anzeigt, wann Aktionen geteilt, blockiert oder verworfen werden.

Fazit & Ausblick

Mit dem Vuex-Mutex-Plugin haben wir ein Werkzeug geschaffen, das alltägliche Probleme in komplexen Vuex-Anwendungen pragmatisch löst.
Ob doppelte Klicks, parallele Requests oder unkontrollierte State-Änderungen – diese Mutex-Logik sorgt für Struktur und Stabilität in asynchronen Abläufen.

Wir haben das Plugin bewusst so gebaut, dass es sich langfristig auch in Pinia-Setups nutzen oder portieren lässt.
Für Teams mit bestehenden Vuex-Codebasen ist es ein effizienter Weg, Legacy-Systeme zu stabilisieren, statt sie komplett umzubauen.

GitHub Repository ansehen
NPM-Paket installieren

Patrick Klinger is a passionate Software Engineer with over 15 years of experience in building modern, user-friendly web applications. His focus lies on creating scalable and maintainable frontend architectures using HTML5, SCSS, TypeScript, and Vue.js. With a background in applied computer science and media informatics, he has successfully contributed to digital transformation projects in the e-commerce sector. Patrick values clean code, teamwork, and a balanced approach to sustainable software development.