[Vuejs]-How to access state variables of a vue-concurrency Task/Instance inside the script tag?

0๐Ÿ‘

I understand this better now.

A Task creates one or more Instances, and those Instances are asynchronous. Therefore we need to handle Instances like any other async code (await, try/catch, then/catch, etc). I have included a few options for doing that.

These code examples replace everything below the line // Now I try to access some of the varibles of the opening post. The catch errors have TypeScript types and avoid EsLint errors where possible:

Option 1 โ€“ then/catch promises:

instance
  .then((response) => {
    console.log(response); // tada
    console.log(instance.value); // tada
  })
  .catch((err: Error) => {
    console.log(err.message); // 'Ruh oh. Something went wrong.'
    console.log(instance.isError); // true
    console.log(instance.error); // the Error object
    // eslint-disable-next-line @typescript-eslint/no-unsafe-member-access
    console.log(instance.error.message); // 'Ruh oh. Something went wrong.'
  });

Option 2 โ€“ try/catch using async wrapper:

const wrapper = async () => {
  try {
    await instance;
    console.log(instance.value); // tada
  } catch (err) {
    if (err instanceof Error) {
      console.log(err.message); // 'Ruh oh. Something went wrong.'
    }
    console.log(instance.isError); // true
    console.log(instance.error); // the Error object
    // eslint-disable-next-line @typescript-eslint/no-unsafe-member-access
    console.log(instance.error.message); // 'Ruh oh. Something went wrong.'
  }
};
void wrapper();

Option 3 โ€“ IIFE:

(async () => {
  await instance;
  console.log(instance.value); // tada
})().catch((err: Error) => {
  console.log(err.message); // 'Ruh oh. Something went wrong.'
  console.log(instance.isError); // true
  console.log(instance.error); // the Error object
  // eslint-disable-next-line @typescript-eslint/no-unsafe-member-access
  console.log(instance.error.message); // 'Ruh oh. Something went wrong.'
});

And actually the original code can be modified because we are not calling the Instance multiple times.

A streamlined version could chain the useTask() with perform() which would then return a single Instance (as opposed to the original code which returned a Task and later assigned the Instance to a variable).

That would save some lines but also require us to update the template and remove references to the task:

<template>
  <div>
    <div v-if="instance.isRunning">Loading...</div>
    <div v-else-if="instance.isError">{{ instance.error.message }}</div>
    <div v-else>
      {{ instance.value }}
    </div>
  </div>
</template>

<script setup lang="ts">
import { timeout, useTask } from 'vue-concurrency';
const instance = useTask(function* () {
  yield timeout(1000);
  if (Math.random() < 0.5) {
    // lets say the API is flaky and errors out often:
    throw new Error('Ruh oh. Something went wrong.');
  } else {
    return 'tada';
  }
}).perform();
// Can include then/catch, try/catch etc here if you want to access the instance variables
</script>

Leave a comment