vue.js 使用@pinia/nuxt时,每次setInterval迭代都会执行setInterval之外的HTTP请求

fkaflof6  于 2023-08-07  发布在  Vue.js
关注(0)|答案(2)|浏览(170)

我正在尝试使用@pinia/nuxt和nuxt 3构建一个计时器。我还想在计时器启动时发出一个http请求来同步我的数据库。
我面临的问题是,每当我调用动作start时,setInterval的每次迭代都会发出http请求,而我只想运行一次。
这是pinia模块。我正在从组件中的onClick事件调用start操作。

state: () => ({
  timer: {
    id: null,
    isRunning: false,
    time: 5,
    timer: 0,
    state: null,
  } as Timer,
}),
actions: {
  start() {
    this.timer.isRunning = true
    this.syncTimer()
    if (!this.timer.timer) {
      this.timer.timer = setInterval(() => {
        if (this.timer.time > 0) {
          this.timer.time--
        } else {
          clearInterval(this.timer.timer)
          this.reset()
        }
      }, 1000)
    }
  },
  stop() {
    this.timer.isRunning = false
    clearInterval(this.timer.timer)
    this.timer.timer = 0
  },
  reset() {
    this.stop()
    this.timer.time = 1500
  },
  syncTimer() {
    backendAPI<Timer>('/api/timer', {
      method: 'POST',
      body: this.timer
    }).then(({ error, data }) => {
      if (!error.value) {
        const id = data.value?.id ?? ""
        this.timer.id = id
        this.timer.state = "created"
      }
    })
  }
}

字符串
自定义提取可组合backendAPI.ts

import type { UseFetchOptions } from 'nuxt/app'
import { useUserStore } from '@/stores/user'
import { defu } from 'defu'

export function backendAPI<T>(url: string, options: UseFetchOptions<T> = {}) {
  const config = useRuntimeConfig()
  const { token } = useUserStore();
  const appToken = useRuntimeConfig().public.appToken

  const defaults: UseFetchOptions<T> = {
    baseURL: config.public.baseURL ?? 'http://localhost:4000',
    key: url,
    params: {
      token: appToken
    },

    headers: token
      ? { Authorization: `Bearer ${token}` }
      : {},
  }

  const params = defu(options, defaults)

  return useFetch(url, params)
}

kwvwclae

kwvwclae1#

正如我在评论中提到的,实现实时特性的正确方法是使用套接字。但是,如果你需要以轮询的方式来做,你可以写一个guard,类似这样:

actions: {
  start() {
    if (this.timer.isRunning) return;

    this.timer.isRunning = true;
    this.syncTimer();

    this.timer.timer = setInterval(() => {
      if (this.timer.time > 0) {
        this.timer.time--;
      } else {
        clearInterval(this.timer.timer);
        this.reset();
      }
    }, 1000);
  },
  // ...
}

字符串
希望这对你有帮助。

niknxzdl

niknxzdl2#

问题似乎与nuxt 3 useFetch函数有关。
nuxt documentation
所有的fetch选项都可以被赋予一个计算值或引用值。这些将被监视,如果它们被更新,则会自动使用任何新值发出新请求。
因此,每次更新计时器值时,useFecth都会自动发出一个新的请求。
在请求中添加watch: false解决了我的问题

backendAPI<Timer>('/api/timer', {
  method: 'POST',
  watch: false,
  body: this.timer
}).then(({ error, data }) => {
  if (!error.value) {
    const id = data.value?.id ?? ""
    this.timer.id = id
    this.timer.state = "created"
  }
})

字符串

相关问题