0

can someone explain, why Promise fires then() function (and also catch() function) when reject is called?

When resolve is called, only then() is trigger - OK

When reject is called, both then() and catch() function are called - Problem

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'));
Felix Kling
  • 795,719
  • 175
  • 1,089
  • 1,143
Martin Kravec
  • 187
  • 2
  • 10

3 Answers3

4

Notice this line:

.then(console.log('logged in'))

then method expects a callback, but you're invoking a function and passing the return value as parameter. If console.log returned a function, that function would be invoked internally by then in case the promise was resolved. But this is not the case, since console.log hasn't a return value! (It just prints and exit).

In javascript, no return value is equal to undefined. So, what you are doing is invoking console.log in any case and passing undefined as parameter. You code is thus equivalent to:

console.log('logged in');
...
  .then(undefined)
  ...

Probably, what you meant is to pass a logging callback as parameter, and let the Promise invoke that callback when it is resolved:

.then(() => console.log('logged in'));

Or, to be more clean about what's happening, you can see it in this way:

function log() {
  console.log('logged in');
}

...
  .then(log);

We are not invoking the function, just passing the reference!

  • Thanks @Cristian Traina for correct answer! and for explanation. It really should be callback function (() => console.log('logged in')). – Martin Kravec Apr 30 '18 at 14:23
2

Promises continue after a catch, although you're trying to wrap a promise in a promise, so you can manually change the behaviour, that is an anti-pattern. Chaining the promise itself would be better, so you are able to handle errors in the promise chain, and then continue execution (so a catch in the middle can still be followed by a then).

There is no need for .catch(error => reject('LogIn failed.')) because your catch statement at the bottom will catch the error if you just return the promise from getSession(). You are trying to create your own Promise, but as there is already a promise being returned from getSession() so what you really want to do is return the promise from that directly.

Finally, you are writing a console.log at the bottom without wrapping it in a callback function, so it is firing synchronously, when the promise is invoked, not when .then is firing.

A neater solution is:

....

    // 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'));
SamMorrowDrums
  • 552
  • 5
  • 15
-1

Calls onFulfilled or onRejected with the fulfillment value or rejection reason of the promise (as appropriate) and returns a new promise resolving to the return value of the called handler.