TLDR:Функция сложна в использовании, когда она иногда возвращает обещание и иногда выдает исключение. При написании функции асинхронной, предпочитает сигнал неисправности путем возврата отклоненного обещания
Ваш конкретный пример запутывает некоторые важные различия между ними:
Потому что вы регулируете ошибки внутри обещание цепь, брошенные исключения получают автоматически преобразован отклонил обещаний. Это может объяснить, почему они кажутся взаимозаменяемыми - это не так.
Рассмотрит ситуацию ниже:
checkCredentials =() => {
let idToken = localStorage.getItem('some token');
if (idToken) {
return fetch(`https://someValidateEndpoint`, {
headers: {
Authorization: `Bearer ${idToken}`
}
})
} else {
throw new Error('No Token Found In Local Storage')
}
}
Это было бы анти-модель, потому что тогда нужно будет поддерживать как асинхронные и синхронизацию случаев ошибок. Это может выглядеть примерно так:
try {
function onFulfilled() { ... do the rest of your logic }
function onRejected() { // handle async failure - like network timeout }
checkCredentials(x).then(onFulfilled, onRejected);
} catch (e) {
// Error('No Token Found In Local Storage')
// handle synchronous failure
}
Не хорошо, и вот именно там, где Promise.reject
(доступен в глобальном масштабе) приходит на помощь и эффективно дифференцирует себя от throw
. Рефакторинг теперь становится:
checkCredentials =() => {
let idToken = localStorage.getItem('some_token');
if (!idToken) {
return Promise.reject('No Token Found In Local Storage')
}
return fetch(`https://someValidateEndpoint`, {
headers: {
Authorization: `Bearer ${idToken}`
}
})
}
Теперь это позволяет использовать только один catch()
для сетевых сбоев и синхронная проверка ошибок из-за отсутствия маркеров:
checkCredentials()
.catch((error) => if (error == 'No Token') {
// do no token modal
} else if (error === 400) {
// do not authorized modal. etc.
}
Оба метода производят точно такую же реакцию. Обработчик '.then()' ловит заброшенное исключение и автоматически превращает его в отклоненное обещание. Поскольку я читал, что заброшенные исключения не особенно быстро выполняются, я бы предположил, что возврат отклоненного обещания может быть немного быстрее для выполнения, но вам нужно будет разработать тест в нескольких современных браузерах, если это важно знать. Я лично использую 'throw', потому что мне нравится читаемость. – jfriend00
@webduvet не с обещаниями - они предназначены для работы с броском. – joews
Один недостаток «бросить» заключается в том, что это не приведет к отвергнутому обещанию, если оно было выброшено из асинхронного обратного вызова, например, setTimeout. http://jsfiddle.net/m07van33/ @Blondie, ваш ответ был верным. –