Как правильно остановить выполнение блока кода при возникновении ошибки из синхронной функции внутри обещания? Более того, как и в функции замены String.replace, можно ли «бросить» туда? Можете ли вы предложить какой-нибудь лучший вариант, или, может быть, подход, более обещающий подход? Функция executor Promise перехватывает синхронные исключения, возникающие в функции executor, и превращает их в отклоненное обещание.
То, что это хорошо делать, зависит от того, что вы хотите, чтобы произошло. Если вы хотите, чтобы обещание в вызывающей функции отклонялось, то вы можете просто выбросить из синхронной функции, и это вызовет переход к обещанию в асинхронном вызове и вызвать отклонение. В противном случае вы также можете использовать обычные синхронные методы, например, возвращать условие ошибки из синхронной функции, проверять эту ошибку в вызывающей программе и затем действовать соответствующим образом. Таким образом, как и любой другой дизайн, это полностью зависит от того, как вы хотите, чтобы ваша синхронная функция вызывалась и как вызывающая сторона должна проверять ошибки или обрабатывать ошибки. Иногда возвращаемый код ошибки является правильным, а иногда выбрасывание исключения является правильным.
Например, в этом случае при вызове randomSyncFunctionThatMightThrow()
throws обещание вызывающего абонента будет отклонено автоматически, и обработчик .catch()
будет hit.
function randomSyncFunctionThatMightThrow() {
// other logic
throw new Error("random error");
}
someFuncThatReturnsPromise().then(arg => {
// bunch of logic here
randomSyncFunctionThatMightThrow();
// other logic here
return someThing;
}).then(result => {
console.log(finalResult);
}).catch(err => {
console.log(err);
});
Пометка функции с помощью asyn c неявно создаст обещание, а также неявно преобразует (uncaught) броски в Promise.reject () и возвращает вводную Promise.resolve. () S. Преимущество состоит в том, что вы можете писать код идентично обычной синхронной функции, но при этом вести себя как обещание, так что вы можете связывать обещания с ним. Это мое понимание неверно?
Звучит правильно для меня. async
функции имеют встроенную try/catch
и автоматически перехватывают любые исключения и превращают их в отклоненное обещание.
Существуют ли недостатки (или преимущества, отличные от того, что я только что описал), которые я должен быть в курсе?
У принудительного асинхронного с обычными обычными результатами возврата асинхронного с обычными результатами возврата есть свои ограничения. Вы бы не использовали его для каждой синхронной функции во всей программе по очевидным причинам сложности кодирования. Асинхронный код требует больше времени на написание и тестирование, поэтому я не go ищу способы заставить обычные синхронные вещи начинать возвращать обещания и заставлять всех вызывающих программ работать с асинхронно. Может быть случайное время, когда некоторый синхронный код легче смешать с асинхронным кодом, если он также имеет дело с обещаниями. Но это не обычное использование синхронного кода.
Я использовал Promise.all (), чтобы объединить результаты нескольких независимых этапов выполнения функции. Я полагаю, это нормально, но есть ли другие способы справиться с этой ситуацией? Или, может быть, это плохая практика? Должен ли я вместо этого цеплять обещания и передавать результаты от обещания до следующего, пока я не достигну уровня, на котором мне нужно использовать их все?
Promise.all()
- для ситуаций, когда вы хотите иметь несколько независимых и параллельных асинхронных цепочек выполнения, все в полете одновременно, и вы просто хотите знать, когда все они будут выполнены и получить все результаты одновременно. Цепочка обещаний предназначена для тех случаев, когда вы хотите упорядочить вещи по порядку один за другим по любому числу причин, но часто потому, что шаг # 2 зависит от результата шага # 1. Вы должны выбрать Promise.all()
вместо цепочки в зависимости от потребностей асинхронного кода (параллельное выполнение или последовательное выполнение).
Помещение синхронного кода в Promise.all()
может работать очень хорошо (вы не даже обернуть его в обещание, так как Promise.all()
также примет возвращаемое значение от запуска функции), но обычно нет никакого смысла. Синхронный код является блокирующим и синхронным, поэтому вы обычно не получаете никакого параллелизма, помещая синхронный код в Promise.all()
. Обычно я просто запускаю синхронный код до или после Promise.all()
и не смешиваю его с фактическими асинхронными обещаниями.
Однако у меня возникают проблемы с выяснением, выполняю ли я это правильный путь.
Я включил ниже альтернативную реализацию. Как правило, я не люблю упаковывать синхронный код в обещания, так что это моя альтернатива. Я использовал функцию async
, так что я могу использовать await
, чтобы синхронные исключения автоматически конвертировались в отклоненное обещание, а контракт вашей функции уже возвращал обещание, так что это просто более простой способ достижения того же результата ( на мой взгляд). Конечно, это всего лишь стиль кодирования, который в значительной степени определяется мнениями.
Вот как я мог бы написать ваш код:
async function fetchFromServerEndpoint(route, routeParams, optQueryParams) {
const finalRoute = route.replace(/{([^{/]*?)}/g, (match, paramName) => {
const paramValue = routeParams[paramName];
if (paramValue === undefined) {
// Here I need to abort execution of the replacer function
// parent promise will be rejected
throw new Error("UNDEFINED_ROUTE_PARAMETER");
}
return paramValue;
});
const queryParms = querystring.stringify(optQueryParams);
const authToken = await MyAPI.getAuthorizationAsync();
return axios.get(`${finalRoute}?${queryParams}`, {
headers: {
Authorization: `Basic ${authToken}`
}
});
}
Если вам действительно не нравится await
здесь вы можете избежать этого, изменив конец на:
return MyAPI.getAuthorizationAsync().then(authToken => {
return axios.get(`${finalRoute}?${queryParams}`, {
headers: {
Authorization: `Basic ${authToken}`
}
});
});
Но, как я уже говорил в комментарии в другом месте, я думаю, что await
- это полезный инструмент (при правильном использовании), который позволяет вам написать более простой код.