/ Gists / Awaited computed from composable - special pattern by me
On gists

Awaited computed from composable - special pattern by me

Vue.js

useAnyComposable.js Raw #

// 1 - composable
import { ref, computed, watchEffect } from 'vue';
import useSomeOtherComposable from './useSomeOtherComposable';

export default function useMyComposable() {
  const { asyncValue1, asyncValue2 } = useSomeOtherComposable();

  const resolved = ref(false);

  // Hodnoty, které vrátíme, až budou splněny podmínky
  const computedValue1 = ref(null);
  const computedValue2 = ref(null);

  // Proměnná promise, která se splní, když budou data připravena
  const dataReady = new Promise((resolve) => {
    watchEffect(() => {
      if (asyncValue1.value === 'desiredValue1' && asyncValue2.value === 'desiredValue2') {
        computedValue1.value = asyncValue1.value;
        computedValue2.value = asyncValue2.value;
        resolved.value = true;
        resolve();
      }
    });
  });


 /*
  // i watchEffect lze zastavit
  
      const dataReady = new Promise((resolve) => {
      const stopEffect = watchEffect(() => {
        if (asyncValue1.value === 'desiredValue1' && asyncValue2.value === 'desiredValue2') {
          computedValue1.value = asyncValue1.value;
          computedValue2.value = asyncValue2.value;
          resolve(); // Vyřeší Promise, když jsou hodnoty požadované
          stopEffect(); // Zastaví watchEffect, protože už není potřeba
        }
      });
    });
 
 */



  // Vrátíme computed hodnoty i promise
  return {
    computedValue1,
    computedValue2,
    dataReady,
    resolved
  };
}

// usage - component
import { defineComponent, onMounted } from 'vue';
import useMyComposable from './useMyComposable'; // another composable which returns computed

export default defineComponent({
  setup() {
    const { computedValue1, computedValue2, dataReady } = useMyComposable();

    onMounted(async () => {
      await dataReady; // Počkáme, až budou hodnoty připravené
      console.log('Values are ready:', computedValue1.value, computedValue2.value);
    });

    return {
      computedValue1,
      computedValue2
    };
  }
});


// 2 - watch insteadof watchEffect
import { ref, watch } from 'vue';
import useSomeOtherComposable from './useSomeOtherComposable';

export default function useMyComposable() {
  const { asyncValue1, asyncValue2 } = useSomeOtherComposable();

  const computedValue1 = ref(null);
  const computedValue2 = ref(null);

  const dataReady = new Promise((resolve) => {
    const stopWatching = watch(
      [asyncValue1, asyncValue2],
      ([newVal1, newVal2]) => {
        if (newVal1 === 'desiredValue1' && newVal2 === 'desiredValue2') {
          computedValue1.value = newVal1;
          computedValue2.value = newVal2;
          resolve(); // Vyřeší Promise, jakmile hodnoty odpovídají požadavkům
          stopWatching(); // Zastaví sledování, protože už není potřeba
        }
      },
      { immediate: true } // Sleduj hned od začátku
    );
  });

  return {
    computedValue1,
    computedValue2,
    dataReady
  };
}


// component usage
import { defineComponent, onMounted } from 'vue';
import useMyComposable from './useMyComposable';

export default defineComponent({
  setup() {
    const { computedValue1, computedValue2, dataReady } = useMyComposable();

    onMounted(async () => {
      await dataReady; // Počkáme, až budou hodnoty připravené
      console.log('Values are ready:', computedValue1.value, computedValue2.value);
    });

    return {
      computedValue1,
      computedValue2
    };
  }
});


// ---------------------------------------------------
// geolocation checker aka MSP 
// ---------------------------------------------------
import { ref, computed } from 'vue';
import { useMyComposable } from './path/to/composable';

export default {
  setup() {
    // Definuj proměnné na úrovni komponenty
    const computedValue1 = ref(null);
    const computedValue2 = ref(null);
    const dataReady = ref(false);

    const check = () => {
      const { computedValue1: cv1, computedValue2: cv2, dataReady: dr } = useMyComposable();
      
      // Přiřaď hodnoty z composable do definovaných proměnných
      computedValue1.value = cv1.value;
      computedValue2.value = cv2.value;
      dataReady.value = dr.value;
    };

    // Spusť funkci nebo ji použij, když potřebuješ načíst data
    check();

    // Můžeš nyní přistupovat k computedValue1 a computedValue2 přímo mimo `check`
    console.log(computedValue1.value, computedValue2.value);

    return {
      computedValue1,
      computedValue2,
      dataReady,
      check,
    };
  },
};