MartinMalinda / vue-concurrency

A library for encapsulating asynchronous operations and managing concurrency for Vue and Composition API.
https://vue-concurrency.netlify.app/
MIT License
352 stars 15 forks source link

usePipeTask raises "c.perform is not a function" when trying to integrate with the Quasar framework #43

Open realflight1 opened 3 years ago

realflight1 commented 3 years ago

I am trying to integrate vue-concurrency with Quasar v2, a Vue 3 framework. When using usePipeTask I get the following error:

Uncaught (in promise) TypeError: c.perform is not a function
    at eval (wrap-utils.ts?76b1:8)
    at tryCatch (runtime.js?96cf:63)
    at Generator.invoke [as _invoke] (runtime.js?96cf:293)
    at Generator.eval [as next] (runtime.js?96cf:118)
    at getNextResult (caf.src.js?b4ef:215)

To reproduce, I created a minimal Quasar project from scratch, installed vue-concurrency, added regenerateRuntime to the webpack configuration (otherwise I get an error) and finally copied the test code for usePipeTask. The changes can be viewed in this commit.

To run the minimal project:

yarn global add @quasar/cli
git clone https://github.com/realflight1/quasar-vue-concurrency-test && cd quasar-vue-concurrency-test
yarn install
quasar dev

Am I missing something in my configuration (most likely) or is this a bug? Thanks!

MartinMalinda commented 3 years ago

Thanks for reporting this. I just tried this in a vite project and could reproduce this bug. The tests for pipeTask are passing, but there seems to be something bad happening in compilation so after minification and bundling, usePipeTask specifically stops working.

If I copy paste the definition for pipeTask directly in my code, it works:

import { useTask } from "vue-concurrency";
import { Task } from "vue-concurrency/dist/vue3/src/Task";

export function usePipeTask<T, U extends any[]>(
  firstTask: Task<any, U>,
  ...restTasks: Task<any, any>[]
): Task<T, U> {
  return useTask(function* (signal, ...args: U) {
    let result = yield firstTask.perform(...args).canceledOn(signal);
    for (let task of restTasks) {
      result = yield task.perform(result).canceledOn(signal);
    }

    return result;
  });
}

I'll try to check what's wrong in the build ouput soon

realflight1 commented 3 years ago

Thanks for the quick response and for confirming. It does work when I copy the code directly into my project, so at least there's a workaround. By the way, looks like my example is a little bit broken (async setup not done correctly) but it can still be tested with console.log or similar in the code.

MartinMalinda commented 3 years ago

@realflight1 AFAIK async / await can be used directly in setup function but in that case your whole componet becomes async in a way and you have to use Suspense and such which is actually not too compatible with vue-concurrency - so I was avoiding this approach so far.

Instead of using async await directly in setup I would usually create a wrap task.

https://vue-concurrency.netlify.app/composing-tasks/

MartinMalinda commented 3 years ago

Might be related to https://github.com/MartinMalinda/vue-concurrency/issues/51

MartinMalinda commented 9 months ago

This is likely fixed in 5.0. Can anyone confirm?