代码之家  ›  专栏  ›  技术社区  ›  TinyTiger

如何在脚本标记中访问vue并发任务/实例的状态变量?

  •  0
  • TinyTiger  · 技术社区  · 4 年前

    我遇到了这个 vue-concurrency 这看起来像是一个处理asyc呼叫的很棒的库。

    但我很难理解如何实现它。

    下面是一个使用Vue并发的简单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”或错误信息。

    但是我想访问script标记中的task和instance变量,此时它们都立即运行,而不用等待异步调用执行。

    我想我可以用 await task.perform() .这样做给了我 task.last?.value 变量但是模板停止工作(变为空白),错误变量不会打印到控制台。

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

    0 回复  |  直到 4 年前
        1
  •  0
  •   TinyTiger    4 年前

    我现在更明白了。

    A. 任务 创建一个或多个 实例 ,还有那些 实例 它们是异步的。因此我们需要处理 实例 和其他异步代码一样(wait、try/catch、then/catch等)。我已经包括了一些这样做的选项。

    这些代码示例替换了所有的代码 // Now I try to access some of the varibles 在开幕式上。catch错误具有TypeScript类型,并尽可能避免EsLint错误:

    选项1——然后/抓住承诺:

    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——生活:

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

    实际上,可以修改原始代码,因为我们没有多次调用该实例。

    一个流线型的版本可能会把整个过程联系起来 useTask() 具有 perform() 然后返回一个 例子 (与返回 任务 后来分配了 例子 对一个变量)。

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

    <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>
    
    推荐文章