Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

What's the reasoning behind the "no-nesting" rule? #42

Closed
EvgenyOrekhov opened this issue Nov 18, 2016 · 5 comments
Closed

What's the reasoning behind the "no-nesting" rule? #42

EvgenyOrekhov opened this issue Nov 18, 2016 · 5 comments

Comments

@EvgenyOrekhov
Copy link

I can't wrap my head around on how to not nest my thens.

return database
    .read({id: 123})
    .then(function (object) {
        /* ... code that changes the object ... */
        return database
            .update(object) // resolves to true
            .then(() => object) // but we need to pass the object to the transport
    })
    .then(transport.respond)
    .catch(transport.error);

How can I not nest here?

@alexander-akait
Copy link

Be good add option onlyCatch (maybe best name) for check only nesting catch in no-nesting rule.

@xjamundx
Copy link
Contributor

xjamundx commented Nov 18, 2016

@EvgenyOrekhov great question thanks!

These rules definitely don't represent the best or the only way to make promises, but in my experience when I've found myself nesting inside of then() usually it's a big warning sign that things are about to get more confusing than I want them to get!

If you can use async/await you'd probably want to do this

let object = await database.read({id: 123})
await database.update(object)
await transport.respond(object)

If you cannot async/await your code and you cannot modify database.update directly you can do this instead:

function updateDB(data) {
    return db.update(data).then(function(success) {
        if (!success) throw new Error('Could not write to DB properly')
        return data
    })
}

Then you can write some super tight promise like this:

return database.read({id: 123})
    .then(mutateObject)
    .then(updateDB)
    .then(transport.respond)
    .catch(transport.error);

There are 100 ways to write promises and in general if you have a success/fail situation instead of returning a boolean you might want to throw and take advantage of that built-in error handling mechanism and then use the normal return for something you want in the success value.

This might not work for you, so in that cases you don't need the rule.

@EvgenyOrekhov
Copy link
Author

I constrained myself to the "JSLint" subset of JavaScript which doesn't allow async/await, so I'll stick to using function declarations. Thanks for the clarification!

@EvgenyOrekhov
Copy link
Author

If you use a promise library (like Bluebird or Q) it likely has the .tap() method which you can use to avoid nesting when you need to return the original argument:

return database
    .read({id: 123})
    .tap(function (object) {
        /* ... code that changes the object ... */
        return database.update(object);
    })
    .then(transport.respond) // transport.respond will receive the object
    .catch(transport.error);

@devhopes-ca
Copy link

devhopes-ca commented Sep 7, 2018

Can someone please help me to fix the no-nesting promises warning with this method?

Here is the code:

getPayoutsPending(uid).then((array) => {
    getPayoutsAmount(array).then((value) => { **// warning  Avoid nesting promises  promise/no-**nesting
    
        var valueTrunc = parseFloat(Math.round(value * 100) / 100).toFixed(2);

        const sender_batch_id = Math.random().toString(36).substring(9);
        const sync_mode = 'false';
        const payReq = JSON.stringify({
            sender_batch_header: {
                sender_batch_id: sender_batch_id,
                email_subject: "You have a payment"
            },
            items: [
                {
                    recipient_type: "EMAIL", 
                    amount: {
                        value: valueTrunc,
                        currency: "CAD"
                    },
                    receiver: "me@gmail.com",
                    note: "Thank you.",
                    sender_item_id: "Payment"
                }
            ]
        });

        paypal.payout.create(payReq, sync_mode, (error, payout) => {
            if (error) {
                console.warn(error.response);
                response.status('500').end();
                throw error;
            } else {
                console.info("payout created");
                console.info(payout);

                updatePaymentsPending(uid, sender_batch_id).then(() => { **// avoid nesting problems** 
                    response.status('200').end();
                    return;
                }).catch((error) => {
                    return console.error(error);
                })
            }
        });
        return null;
    }).catch((error) => {
        return console.error(error);
    })
    return null;
}).catch((error) => {
    return console.error(error);
})

There are two lines ... marked // avoid nesting problems that are causing the warnings.

Please help as what I have done doesn't seem to work.
Much appreciated

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Projects
None yet
Development

No branches or pull requests

4 participants