Repository: nuxt/nuxt
File: packages/nuxt/src/app/composables/asyncData.ts (TypeScript)

Code before:
          asyncData.status.value = 'error'
        })
        .finally(() => {
          if ((promise as any).cancelled) { return }

          if (pendingWhenIdle) {
            asyncData.pending.value = false
          }

          delete nuxtApp._asyncDataPromises[key]
        })
      nuxtApp._asyncDataPromises[key] = promise
      return nuxtApp._asyncDataPromises[key]!
    },
    _execute: debounce((...args) => asyncData.execute(...args), 0, { leading: true }),
    _default: options.default!,
    _deps: 0,
    _init: true,
    _hash: isDev ? createHash(_handler, options) : undefined,
    _off: () => {
      unsubRefreshAsyncData()
      asyncData._init = false
      // TODO: disable in v4 in favour of custom caching strategies
      if (purgeCachedData && !hasCustomGetCachedData) {
        clearNuxtDataByKey(nuxtApp, key)
        asyncData.execute = () => Promise.resolve()
      }
    },
  }

  return asyncData
}

// Used to get default values
const getDefault = () => asyncDataDefaults.value
const getDefaultCachedData: AsyncDataOptions<any>['getCachedData'] = (key, nuxtApp, ctx) => {
  if (nuxtApp.isHydrating) {
    return nuxtApp.payload.data[key]
  }

  if (ctx.cause !== 'refresh:manual' && ctx.cause !== 'refresh:hook') {
    return nuxtApp.static.data[key]
  }
}

function createHash (_handler: () => unknown, options: Partial<Record<keyof AsyncDataOptions<any>, unknown>>) {
  return {
    handler: hash(_handler),
    transform: options.transform ? hash(options.transform) : undefined,
    pick: options.pick ? hash(options.pick) : undefined,
    getCachedData: options.getCachedData ? hash(options.getCachedData) : undefined,

Review comment (bug):
Hi @danielroe! I guess it was meant to be:
`if (!nuxtApp._asyncData[key]?._init) {`

I'm not sure, but I don't see any place where _init could be switched from `false` to `true`. And it seems like there can be a bug if an asyncData is going to be cleared and a new asyncData with the same key is created at this moment.

Code after:
          asyncData.status.value = 'error'
        })
        .finally(() => {
          if ((promise as any).cancelled) { return }

          if (pendingWhenIdle) {
            asyncData.pending.value = false
          }

          delete nuxtApp._asyncDataPromises[key]
        })
      nuxtApp._asyncDataPromises[key] = promise
      return nuxtApp._asyncDataPromises[key]!
    },
    _execute: debounce((...args) => asyncData.execute(...args), 0, { leading: true }),
    _default: options.default!,
    _deps: 0,
    _init: true,
    _hash: isDev ? createHash(_handler, options) : undefined,
    _off: () => {
      unsubRefreshAsyncData()
      asyncData._init = false
      // TODO: disable in v4 in favour of custom caching strategies
      if (purgeCachedData && !hasCustomGetCachedData) {
        nextTick(() => {
          if (!asyncData._init) {
            clearNuxtDataByKey(nuxtApp, key)
            asyncData.execute = () => Promise.resolve()
          }
        })
      }
    },
  }

  return asyncData
}

// Used to get default values
const getDefault = () => asyncDataDefaults.value
const getDefaultCachedData: AsyncDataOptions<any>['getCachedData'] = (key, nuxtApp, ctx) => {
  if (nuxtApp.isHydrating) {
    return nuxtApp.payload.data[key]
  }

  if (ctx.cause !== 'refresh:manual' && ctx.cause !== 'refresh:hook') {
    return nuxtApp.static.data[key]
  }
}

function createHash (_handler: () => unknown, options: Partial<Record<keyof AsyncDataOptions<any>, unknown>>) {
  return {