简体   繁体   中英

How to simplify deep nested promises

I have come across a situation where I need to break at every "else" clause in a then() , and this doesn't look any better than nested callbacks, this is a login process:

User.findOne({
    username: username
}).exec()
    .then(user => {
        if (user) {
            return user.verifyPassAsync()
                .then(matched => {
                    if (matched) {
                        return User.getBriefProfile(username))
                            .then(emp => {
                                if (emp) {
                                    return saveToSession(emp);
                                } else {
                                    //return 
                                }})
                    } else {
                        //return ...
                    }})
        } else {
        // return false
        }
    })

Is there any way I can simplify this?

Not really, as you're not (only) nesting promises here but rather conditionals. If written with async/await (ES7), your function would look like

var user = await User.findOne({username}).exec();
if (user) {
    var matched = await user.verifyPassAsync();
    if (matched) {
        var emp = await User.getBriefProfile(username);
        if (emp) {
            return saveToSession(emp);
        } else {
            // return …;
        }
    } else {
        // return …;
    }
} else {
    // return …;
}

As you can see, the nesting is inherent to your program. It's a bit simplified already though (no nesting for then calls), and you can do this right now with Promise.coroutine and ES6 generators.

Your best bet might be to throw an error in each else , and linearise the chain with that, .catch ing it in the end. Of course, if you are doing the same thing in each else block, then you could as well write

var user = await User.findOne({username}).exec();
if (user)
    var matched = await user.verifyPassAsync();
if (matched)
    var emp = await User.getBriefProfile(username);
if (emp) {
    return saveToSession(emp);
else
    // return …;

which easily translates back to then callbacks:

User.findOne({username: username}).exec()
.then(user =>
    user && user.verifyPassAsync()
).then(matched =>
    matched && User.getBriefProfile(username);
).then(emp =>
    emp ? saveToSession(emp) : …;
);

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM