【问题标题】:How to access state variables of a vue-concurrency Task/Instance inside the script tag?如何访问脚本标签内的 vue 并发任务/实例的状态变量?
【发布时间】:2022-02-18 08:25:30
【问题描述】:

我遇到了这个vue-concurrency,它看起来像是一个处理异步调用的好库。

但我无法理解如何实现它。

这是一个使用 vue-concurrency 的简单 Vue 组件:

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

<script setup lang="ts">
import { timeout, useTask } from 'vue-concurrency';
const task = 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';
  }
});
const instance = task.perform();
// Now I try to access some of the varibles
console.log(instance.isError); // runs immediatley, always returns "false"
console.log(instance.error); // runs immediatley, always returns "null"
console.log(instance.value); // runs immediatley, always returns "null"
console.log(task.isError); // runs immediatley, always returns "false"
console.log(task.last?.isError); // runs immediatley, always returns "false"
console.log(task.last?.error); // runs immediatley, always returns "null"
console.log(task.last?.value); // runs immediatley, always returns "null"
</script>

此组件进行虚假的 API 调用。停顿一秒钟。然后将抛出错误或返回“tada”字符串。

当前代码在模板中运行,它显示“正在加载...”,然后显示“tada”或错误消息。

但我想访问脚本标签内的任务和实例变量,目前它们都立即运行,无需等待异步调用执行。

我想我可以通过使用 await task.perform() 来解决这个问题。这样做会给我task.last?.value 变量。但是模板停止工作(变为空白)并且错误变量不会打印到控制台。

那么如何正确访问脚本标签内的 vue 并发任务/实例的状态值呢?

【问题讨论】:

标签: vue.js vuejs3


【解决方案1】:

我现在更明白了。

一个Task会创建一个或多个Instances,而那些Instances是异步的。因此,我们需要像处理任何其他异步代码(await、try/catch、then/catch 等)一样处理 Instances。为此,我提供了一些选项。

这些代码示例替换了开头帖子// Now I try to access some of the varibles 行下方的所有内容。 catch 错误具有 TypeScript 类型,并尽可能避免 EsLint 错误:

选项 1 - then/catch 承诺:

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.'
  });

选项 2 - 使用异步包装器尝试/捕获:

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();

选项 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.'
});

其实原来的代码是可以修改的,因为我们没有多次调用Instance。

精简版本可以将useTask()perform() 链接起来,然后返回单个Instance(与返回Task 及更高版本的原始代码相反将 Instance 分配给变量)。

这将节省一些行,但也需要我们更新模板并删除对任务的引用:

<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>

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 2020-12-02
    • 1970-01-01
    • 2019-01-20
    • 2021-10-26
    • 1970-01-01
    • 2011-02-05
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多