Я использую Vue 3 с Nuxt 3 и Vite и столкнулся со странной ошибкой. Это происходит почти везде в моем приложении, когда я пытаюсь использовать useFetch внутри составного объекта.
Например, у меня есть следующая компоновка, позволяющая проверить, можно ли отобразить кнопку в зависимости от роли пользователя:
export function useCheckerRole(policies){
const {data, error} = await useFetch("/api/role-checker", {
method: "POST",
body: policies
})
if (data.value) {
return data.value
}
if (error.value) {
throw new Error("an error occured");
}
}
Затем мне нужно будет передавать такие политики всякий раз, когда мне нужно будет проверить их роли.
const policies = await useCheckerRole([
{
component_ask: 'some-button',
role_ask: 'administrator'
}
])
который затем возвращает что-то вроде этого из API:
[{
component_ask: 'some-button',
role_ask: 'administrator',
status: 'approved'
}]
Ошибка проявляется, когда я монтирую useCheckerRole в двух разных компонентах на одной странице.
Например, в моем компоненте верхней панели я использую useCheckerRole, чтобы определить, должна ли отображаться конкретная кнопка или меню, в зависимости от роли пользователя. Между тем, в другом месте страницы у меня есть еще одна кнопка, требующая аналогичной проверки на основе ролей.
Верхняя панель отправляет это в средство проверки ролей, а затем немедленно записывает результат.
const policies = await useCheckerRole([
{
component_ask: 'top-bar-button',
role_ask: 'administrator'
}
]).catch((error)....)
console.info("topBar Policies result", policies)
Дочерняя страница отправляет это в useCheckerRole и немедленно регистрирует результат.
const policies = await useCheckerRole([
{
component_ask: 'child-page-button',
role_ask: 'administrator'
},
{
component_ask: 'child-page-other-button',
role_ask: 'administrator'
},
]).catch((error)....)
console.info("Child Policies result", policies)
теперь результат Topbar выглядит интересно:
[
{
component_ask: 'child-page-button',
role_ask: 'administrator',
status: "approved"
},
{
component_ask: 'child-page-other-button',
role_ask: 'administrator',
status: "rejected"
},
]
Обратите внимание, что это было не то, что компонент Topbar отправил в useCheckerRole, а то, что отправил ChildPage.
[
{
component_ask: 'top-bar-button',
role_ask: 'administrator',
status: "approved"
},
]
ChildPage также получил тот же результат, что и Topbar:
[
{
component_ask: 'child-page-button',
role_ask: 'administrator',
status: "approved"
},
{
component_ask: 'child-page-other-button',
role_ask: 'administrator',
status: "rejected"
},
]
Это заставило меня понять, что составные объекты не так изолированы, как я думал при использовании useFetch, или, возможно, я делаю что-то очень неправильно. Потому что похоже, что оба компонента одновременно вызывали одну и ту же неизолированную функцию, даже если указанная функция должна быть изолированной.
Первоначальный результат в TopBar был правильным. Однако когда ChildPage также вызвал ту же функцию, она каким-то образом переопределила результат, что, к сожалению, не было тем, что запрашивал TopBar.
Есть ли у кого-нибудь еще эта проблема?
@EstusFlask Эстус, спасибо, это помогло мне понять, в чем проблема. Я опубликую обновление. Большое спасибо. Я использую Nuxt 3.7.4, а также применил кеш: «no-cache» в опциях, вместо этого он воспроизвел для меня еще одну ошибку, но это помогло мне добраться туда, где мне нужно было отследить странный вывод. так что спасибо.
Я думаю, это не из-за «изоляции», а из-за кэша useFetch
. useFetch
использует клавишу , чтобы предотвратить повторную выборку одних и тех же данных. По умолчанию key
— это предоставленный URL-адрес, который одинаков в ваших двух компонентах. Можете ли вы попробовать назначить им другой ключ?
export function useCheckerRole(policies){
const {data, error} = await useFetch("/api/role-checker", {
method: "POST",
body: policies,
key: policies.component_ask
})
if (data.value) {
return data.value
}
if (error.value) {
throw new Error("an error occured");
}
}
ОП предполагает, что это может быть как-то связано с кешированием, но я совершенно уверен, что Nuxt не использует кеш для POST по умолчанию, это было бы большой ошибкой с их стороны
@EstusFlask ах, вы правы, извините, я не заметил, что это POST
, тогда нам может понадобиться минимальная репродукция для расследования.
@YueJIN, спасибо, ваш ответ очень приблизил меня к моей проблеме. каким-то образом благодаря этому мне удалось обнаружить странную проблему.
Поиграв направо и налево с решениями, которые дали Юэ Цзинь и Эстус Фласк, я наконец нашел проблему. Я наткнулся на эту статью — Nuxt 3 useFetch — правильно ли вы его используете? и прочитайте следующее высказывание автора:
Как правило, при использовании компонуемых объектов их следует вызывать только внутри; функция настройки, плагины и промежуточное программное обеспечение маршрута. Попытка использовать эту компоновку за пределами этой области приведет к ошибкам, которые повлияют на производительность приложения.
В статье он продемонстрировал, как возникла ошибка после упаковки useFetch в функцию. Сразу после этого я увидел, что моя функция действительно оборачивает составной объект, который оборачивает составной объект useFetch.
<script setup>
const policy_list = ref([...])
async function checkRole(){
const policies = await useCheckerRole(policy_list .value).catch((error)=>
{...}
)
}
checkRole();
</script>
что useCheckerRole является составным элементом функции, использующей useFetch. Итак, странный баг действительно появился.
Я решил проверить это, создав обычную функцию и поместив ее за пределы папки Composables; в папке с именем lib.
Внутри roleChecker.ts я больше не использую useFetch. Вместо этого я использую $fetch для вызова моего API и возврата их.
export default function roleChecker(
url: string,
options: { [key: string]: any },
source?: string
) {
return new Promise<any>(async (resolve, reject) => {
console.info("roleChecker initialized");
$fetch(url, options)
.then((res) => {
resolve(res);
})
.catch((error) => {
reject(error);
});
});
}
Теперь для каждого моего компонента я наконец могу вызвать roleChecker внутри любой функции, и ошибки меня больше не беспокоят.
<script setup>
import roleChecker from "/lib/roleChecker"
const policy_list = ref([...])
async function checkRole(){
const policies = await roleChecker(policy_list .value).catch((error)=>
{...}
)
}
checkRole();
</script>
Что такое версия Nuxt? Можно попробовать добавить
cache: false
к запросам. Более вероятно, что это API обеспечивает нежелательное кэширование POST-запросов, обычно этого не должно происходить.