Я использую axios в своем приложении VueJS. На данный момент в каждом компоненте я использую переменную в каждом компоненте, чтобы проверить, нажал ли пользователь кнопку перед запуском вызова axios. Это приводит к большому количеству повторяющегося кода, поэтому я подумал о переносе вызовов axios в функцию "uniqueAxios", например:
const urlsAPI = [];
const uniqueAxios = async (method, url, data) => {
if (urlsAPI.includes(url)) {
console.info('Already called!!');
Promise.reject(new Error('Already called'));
} else {
urlsAPI.push(url);
await axios[method](url, data)
.then((res) => {
console.info('OK');
console.info(res);
return Promise.resolve(res);
})
.catch((e) => {
console.info('KO');
console.info(e);
return Promise.reject(e);
});
}
};
Но когда я использую эту функцию в своем компоненте, вот так:
await uniqueAxios(
'post',
`${process.env.VUE_APP_API_URL}/XXX`,
)
.then((res) => {
console.info(res);
})
.catch((e) => {
console.info(e);
Консоль выдает ошибку: TypeError: res is undefined. Однако с API связываются. Просто я не могу справиться с then и catch, которые у меня были раньше, когда я напрямую использовал axios.
Я уверен, что функция упаковки uniqueAxios неверна.
Кто-нибудь знает, как мне с этим справиться?
Заранее спасибо.





У вас несколько проблем, во-первых, вы ничего не возвращаете в своей функции.
const uniqueAxios = async (method, url, data) => {
if (urlsAPI.includes(url)) {
console.info('Already called!!');
Promise.reject(new Error('Already called'));
} else {
urlsAPI.push(url);
return await axios[method](url, data) // You need to return the axios
.then((res) => {
console.info('OK');
console.info(res);
return Promise.resolve(res); // This line return inside the promise axios not the function
})
.catch((e) => {
console.info('KO');
console.info(e);
return Promise.reject(e);
});
}
};
Во-вторых, вы ждете и ничего не делаете. Теперь с этим изменением вы можете ожидать свою функцию, как это, и регистрировать ответ.
const response = await uniqueAxios(
'post',
`${process.env.VUE_APP_API_URL}/XXX`,
)
console.info(response)
Да, вы делаете то же самое, что и второй блок. Это лучше всего, сохраните ответ внутри константы и сделайте что-нибудь с ним;) Но поймите, может быть, в другой раз, когда вы возвращаете блок, подобный ir then, это возвращает внутри обещания, а не начального оператора блока (то же самое с map, filter . ...).
[EDIT: это работает, но ответ, который я выбрал, намного лучше]
На самом деле я нашел решение:
let urlsAPI = [];
const uniqueAxios = async (method, url, data) => {
if (urlsAPI.includes(url)) {
throw new Error('Axios already called');
}
urlsAPI.push(url);
const t = {
type: 0,
content: null,
};
await axios[method](url, data)
.then((res) => {
t.content = res;
t.type = 1;
})
.catch((e) => {
t.content = e;
})
.finally(() => {
urlsAPI = urlsAPI.filter((u) => u !== url);
});
if (t.type) {
return t.content;
}
throw t.content;
};
Ваш исходный код
const urlsAPI = [];
const uniqueAxios = async (method, url, data) => {
if (urlsAPI.includes(url)) {
console.info('Already called!!');
Promise.reject(new Error('Already called'));
} else {
urlsAPI.push(url);
await axios[method](url, data)
.then((res) => {
console.info('OK');
console.info(res);
return Promise.resolve(res);
})
.catch((e) => {
console.info('KO');
console.info(e);
return Promise.reject(e);
});
}
};
Все функции async возвращают обещание, даже что-то вроде:
async function three() {
return 3;
}
или это
async function belch() {
throw new Error("Belch!");
}
который будет разрешаться или отклоняться в зависимости от того, была ли выдана ошибка.
Поскольку вы явно не возвращаете значение, возвращаемое значение представляет собой обещание, которое разрешается как undefined (если не выдается ошибка, в этом случае оно отклоняется).
Ваш код был бы чище (и работал!), если бы вы просто сказали что-то вроде этого:
const inFlightUrls = new Set();
const uniqueAxios = async (method, url, data) => {
const inflight = inFlightUrls.has(url);
if (inFlight) {
throw new Error('Already called');
}
inFlightUrls.add(url);
const res = axios[method](url, data)
.finally( () => inflightUrls.delete(url) ) ;
return res ;
};
Приведенная выше функция возвращает обещание, которое либо разрешается с помощью объекта ответа Axios, либо отклоняется с ошибкой (либо от Axios, либо от вас).
Большое спасибо за ваш ответ. Что вы думаете об ответе, который я опубликовал после прочтения ответа Рафаэля? Мне нужен ваш опыт в этом. Это работает для меня в моем приложении, но я, возможно, написал неправильный код.
Вероятно, это работает, но это ужасно сложно. Весь смысл async/await в том, что это синтаксический сахар, который избавляет от всех обратных вызовов и дает вам более простой процедурный код.
Я попробовал ваш ответ, он работает как шарм, и Set - действительно хорошая идея ... Я проголосовал за него вместо своего, спасибо.
Спасибо, Рафаэль, мне удалось решить мою проблему, и я опубликовал ответ. Вы можете пересмотреть его, если хотите.