为什么Promise回报也决定拒绝

时间:2018-04-30 12:36:47

标签: javascript promise async-await es2017

有人可以解释一下,为什么Promise会在调用reject时触发then()函数(以及catch()函数)?

调用resolve时,只触发then() - OK

当调用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 个答案:

答案 0 :(得分:4)

注意这一行:

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

then方法需要callback,但您正在调用函数并将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);

我们没有调用该函数,只是传递引用!

答案 1 :(得分:2)

承诺在捕获后继续,虽然您尝试在承诺中包含承诺,因此您可以手动更改行为,这是一种反模式。链接承诺本身会更好,所以你能够处理promise链中的错误,然后继续执行(所以中间的一个catch仍然可以跟随一个)。

不需要.catch(error => reject('LogIn failed.')) ,因为如果您只是从getSession()返回承诺,那么底部的catch语句将捕获错误。你正在尝试创建自己的Promise,但是因为已经有getSession()的回复,所以你真正想做的就是直接从中返回承诺。

最后,您在底部编写console.log而不将其包装在回调函数中,因此在调用promise时同步触发,而不是在.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'));

答案 2 :(得分:-1)

使用履行的履行价值或拒绝原因(视情况而定)调用onFulfilled或onRejected,并返回一个新的承诺,解析为被调用者的返回值。