Почему Promise возвращается и разрешается при отклонении
Может кто-нибудь объяснить, почему Promise запускает функцию then() (а также функцию catch()) при вызове reject?
Когда решается вызов, только тогда () триггер - ОК
Когда вызывается reject, вызываются функции then() и catch() - Проблема
static logIn(email, password) {
async function getSession () {
let data = new FormData();
data.append('email', email);
data.append('password', password);
const response = await fetch(
url,
{
method: 'POST',
mode: 'cors',
body: data,
cache: 'no-cache',
headers: {
'Accept': 'application/json',
},
}
);
const json = await response.json();
return json;
}
return new Promise((resolve, reject) => {
getSession()
.then(json => {
if (json.status === 'ok') {
resolve('OK');
} else {
reject('LogIn failed.');
}
})
.catch(error => reject('LogIn failed.'))
});
};
logIn()
.then(console.log('logged in'))
.catch(error => console.log('not logged in'));
3 ответа
Обратите внимание на эту строку:
.then(console.log('logged in'))
then
Метод ожидает обратного вызова, но вы вызываете функцию и передаете return
значение в качестве параметра. Если console.log вернул функцию, эта функция будет вызвана внутри then
в случае, если обещание было выполнено. Но это не так, так как console.log не имеет возвращаемого значения! (Он просто печатает и выходит).
В JavaScript нет возвращаемого значения, равного undefined
, Итак, в любом случае вы вызываете console.log и передаете в качестве параметра значение undefined. Ваш код, таким образом, эквивалентен:
console.log('logged in');
...
.then(undefined)
...
Вероятно, вы имели в виду передать обратный вызов журналирования в качестве параметра и позволить Promise вызывать этот обратный вызов, когда он разрешен:
.then(() => console.log('logged in'));
Или, чтобы быть более ясным о том, что происходит, вы можете увидеть это следующим образом:
function log() {
console.log('logged in');
}
...
.then(log);
Мы не вызываем функцию, просто передаем ссылку!
Обещания продолжаются после улова, хотя вы пытаетесь обернуть обещание в обещание, чтобы вы могли вручную изменить его поведение, что является анти-паттерном. Цепочка самого обещания была бы лучше, так что вы можете обрабатывать ошибки в цепочке обещаний, а затем продолжать выполнение (так, чтобы за ловушкой в середине все еще мог последовать оператор then).
Там нет необходимости .catch(error => reject('LogIn failed.'))
потому что ваш оператор catch внизу поймает ошибку, если вы просто вернете обещание от getSession()
, Вы пытаетесь создать свое собственное Обещание, но так как обещание уже возвращается getSession()
Итак, что вы действительно хотите сделать, это вернуть обещание от этого напрямую.
Наконец, вы пишете console.log
внизу, не оборачивая его в функцию обратного вызова, поэтому он запускается синхронно, когда вызывается обещание, а не когда .then
стреляет.
Более аккуратное решение:
....
// return the promise from getSession, why wrap it in another?
return getSession()
.then(json => {
if (json.status === 'ok') {
return 'OK';
} else {
// Throwing an error in a then callback will trigger the catch block below
throw new Error('LogIn failed.');
}
});
}
logIn()
.then(() => console.log('logged in'))
.catch(error => console.log('not logged in'));
Вызывает onFulfilled или onRejected со значением выполнения или причиной отклонения обещания (в зависимости от ситуации) и возвращает новое обещание, разрешающееся в возвращаемое значение вызываемого обработчика.