Почему Promise возвращает также Resolve on Reject

может кто-нибудь объяснить, почему Promise запускает функцию then() (а также функцию catch()) при вызове reject?

Когда вызывается разрешение, только then() срабатывает - ОК

Когда вызывается 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'));

person Martin Kravec    schedule 30.04.2018    source источник
comment
Что регистрируется?   -  person Parama Kar    schedule 30.04.2018
comment
У вас есть несколько then, какой из них, по вашему мнению, вызывается неправильно в случае отказа?   -  person Andrew Marshall    schedule 30.04.2018


Ответы (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);

Мы не вызываем функцию, просто передаем ссылку!

person Cristian Traìna    schedule 30.04.2018
comment
Спасибо @Cristian Traina за правильный ответ! и для объяснения. Это действительно должна быть функция обратного вызова (() => console.log('logged in')). - person Martin Kravec; 30.04.2018

Обещания продолжаются после перехвата, хотя вы пытаетесь обернуть обещание в обещание, поэтому вы можете вручную изменить поведение, что является антишаблоном. Цепочка самого промиса была бы лучше, так что вы можете обрабатывать ошибки в цепочке промисов, а затем продолжать выполнение (так что за уловом в середине все еще может следовать 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'));
person SamMorrowDrums    schedule 30.04.2018

Вызывает onFulfilled или onRejected со значением выполнения или причиной отклонения обещания (в зависимости от ситуации) и возвращает новое обещание, разрешающее возвращаемое значение вызываемого обработчика.

person Parvinder Singh Saluja    schedule 30.04.2018