Я использую вспомогательную функцию (fetchGet
), возвращающую асинхронную функцию, которая возвращает обещание (fetchWrapper
).
Нужно ли объявлять эту вспомогательную функцию как асинхронную по отношению к самой себе, возвращающей обещание?
В моем случае здесь используется выборка, которую нужно ожидать в моей первой функции fetchWrapper
(здесь упрощено для удобочитаемости):
// returns a promise
async function fetchWrapper(url, method) {
const response = await fetch(url, {method: method});
if (!response.ok) {
throw new Error("HTTP error " + response.status);
}
return response;
}
async function fetchGet(url) {
return fetchWrapper(url, 'GET');
}
async function getSpecificData() {
return fetchGet('/a/specific/url');
}
Нужно ли мне объявлять функцию fetchGet
как асинхронную функцию, как указано выше, чтобы она возвращала обещание?
Или я могу просто объявить это как обычную синхронную функцию, как показано ниже?
(это действительно тот же случай для функции getSpecificData
)
function fetchGet(url) {
return fetchWrapper(url, 'GET');
}
Does this helper function need to be declared as asynchronous to itself return a promise?
Нет.
async
функции всегда возвращают обещания, даже если оператор return
возвращает что-то, что не является обещанием. async
функции позволяют вам управлять другими промисами внутри них, используя await
Вы можете явно вернуть обещание из любой функции.
Does a function need to be declared as asynchronous to return a promise?
Нет, совсем нет. На самом деле, обещания существовали задолго до того, как async
начала функционировать.
Ваша обертка может быть просто:
function fetchGet(url) {
return fetchWrapper(url, 'GET');
}
Вам не нужно async
, если вы не используете await
внутри функции. Вы можете использовать выберите, чтобы отметить асинхронный характер функции, например, в качестве документации в коде (подсказки по коду в IDE и т. д.). Но это не требуется.
Примечание: у вас проблема с fetchWrapper
. Это преуспевает со значением выполнения undefined
, если есть ошибка HTTP. Это означает, что код, использующий его, должен проверить значение выполнения, чтобы увидеть, является ли оно undefined
, прежде чем использовать его. Я бы рекомендовал делать ошибки ошибок HTTP (отказы):
async function fetchWrapper(url, method) {
const response = await fetch(url, {method: method});
if (!response.ok) {
throw new Error("HTTP error " + response.status);
}
return response;
}
«В противном случае он вам не нужен.» субъективная причина его использования заключается в том, что async
дает понять, какая функция является асинхронной. Вам нужно только посмотреть на подпись, а не проверять, что делает код. На самом деле, с кодом OP fetchGet
будет асинхронным, но вы должны следить за вызовом функции внутри него, чтобы увидеть это. Я не сомневаюсь, что есть автоматизированные инструменты, которые смогут извлекать подписи для вас, так что вам даже не нужно искать код самостоятельно, а значит, еще проще увидеть, что есть что.
@ T.J.Crowder, ты прав с моей неуклюжей fetchWrapper, я слишком упростил ее. Я редактирую вашу краткую альтернативу
Вам просто нужно объявить функцию как async
, когда внутри функции вы собираетесь ожидать результата, поэтому оба:
// returns a Promise because it's async (resolved with 'value')
async function fetchGet(url) {
const value = await fetchWrapper(url, 'GET');
return value;
}
// returns a Promise because fetchWrapper is a Promise
function fetchGet(url) {
return fetchWrapper(url, 'GET');
}
// returns a Promise, just because it's async
async function fetchGet(url) {
// nothing
}
// returns undefined
function fetchGet(url) {
// nothing
}
Работайте точно так же для этих вызывающих абонентов:
fetchGet('url').then(value => {...})
const value = await fetchGet(url)
async
функции автоматически возвращают промис, если в вашем коде ничего не возвращается (независимо от того, что возвращает ваш код, результат будет заключен в промис).