Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Awaiting a function then awaiting useAsyncData throws "nuxt instance unavailable" error - but only in a composable #19724

Closed
Jamiewarb opened this issue Mar 15, 2023 · 4 comments

Comments

@Jamiewarb
Copy link
Contributor

Environment

  • Operating System: Darwin
  • Node Version: v18.1.0
  • Nuxt Version: 3.3.1
  • Nitro Version: 2.3.1
  • Package Manager: pnpm@7.25.0
  • Builder: vite
  • User Config: -
  • Runtime Modules: -
  • Build Modules: -

Reproduction

https://github.com/Jamiewarb/nuxt-useasync-repro

  • Clone repo
  • pnpm install && pnpm dev
  • Open localhost:3000
  • Observe error

'~/composables/useTest' contains two functions, the difference being the lines swapped around. One works, and one doesn't, so you can see both.

Copying the non-working function directly into the <script> tag of app.vue means it starts working again.

Describe the bug

Within a component, when calling a function that uses await, there is a bug that appears depending on the order of the await's. I assume this is to do with the compiler and Nuxt's composables, but I'm not sure how to describe it.

The below doesn't work, and throws a nuxt instance unavailable:

export async function useTestDoesntWork() {
  await fn();
  await useAsyncData(async () => {});
}

But swapping the order is fine:

export async function useTestWorks() {
  await useAsyncData(async () => {});
  await fn();
}

Furthermore, taking the non-working code and putting it directly into a component <script setup> means it works again:

<script setup>
await fn();
await useAsyncData(async () => {});
</script>

image

Additional context

No response

Logs

nuxt instance unavailable

at Module.useAsyncData (./node_modules/.pnpm/nuxt@3.3.1/node_modules/nuxt/dist/app/composables/asyncData.js:24:38)
at Module.useTestDoesntWork (./composables/useTest.ts:5:31)
at process.processTicksAndRejections (node:internal/process/task_queues:95:5)
at async setup (./app.js:10:116)
@Jamiewarb Jamiewarb changed the title Awaiting a function then awaiting useAsyncData throws "nuxt instance unavailable" error - but only in a compos Awaiting a function then awaiting useAsyncData throws "nuxt instance unavailable" error - but only in a composable Mar 15, 2023
@danielroe
Copy link
Member

I think you can see more about the reason here in https://nuxt.com/docs/guide/concepts/auto-imports#using-vue-and-nuxt-composables.

Basically, a rule of thumb is that you cannot await before a vue/nuxt composable unless it's in a protected environment, namely <script setup>, a Nuxt plugin or Nuxt route middleware.

Outside of those environments, you must use callWithNuxt to pass the Nuxt instance to the composable or it will be lost. We have a DX improvement in mind which you can track via #14805.

@Jamiewarb
Copy link
Contributor Author

Thanks for the fast reply and thorough information. I'll take a look at callWithNuxt :)

@Jamiewarb
Copy link
Contributor Author

Jamiewarb commented Mar 15, 2023

To confirm, our own composables called from within <script setup> are not in the protected environment, because they are in a different file?

@danielroe
Copy link
Member

Yes. The reason those environments are protected is that we (Vue for <script setup>, Nuxt for plugins + middleware) run a transform to preserve the context on either side of each await call. But if you call a composable then it we can't 'follow' that call into a different file and transform that one as well.

@danielroe danielroe closed this as not planned Won't fix, can't repro, duplicate, stale Mar 16, 2023
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Projects
None yet
Development

No branches or pull requests

2 participants