node.js ~ constructing chained sequence of Promise resolves

后端 未结 2 2077
醉梦人生
醉梦人生 2020-12-10 23:21

Can anyone suggest a better way to structure this use of Promises? I\'m newish to Promises and am wondering if I\'m missing something about how to construct this a chain of

2条回答
  •  难免孤独
    2020-12-11 00:08

    The key thing to remember about promises is that then returns a new promise (as does catch). How that new promise is settled depends on what you return from the handler: If you return a promise, the new promise from then/catch is slaved to the one that you returned; if you return a value, the new promise is resolved with that value.

    So you can chain them together. Think of the then and catch handlers as transforming filters the ultimate result flows through.

    Note also that if you have a starting point that gives you a promise (cn.connect()), you don't need new Promise: Just use then and catch to transform what passes through the chain by returning the (new) resolution value.

    Another key thing to remember is that if a catch handler returns a value, it converts a rejection into a resolution. To continue down the rejection path, a catch handler must either throw an exception or return a promise that is/will be rejected.

    Finally: require calls should always be at the beginning of the module.

    So, without removing your conversion of rejections to resolutions (more on that in a moment):

    var sql = require('mssql');
    var myDao = require('./myDao');
    
    module.exports = {
    
        dbConnection: function () {
            return { user: 'sa', password: 'mypassword', server: 'localhost', database: 'mydb' };
        },
    
    
        CanIConnectToTheDB: function () {
            var cn = new sql.ConnectionPool(myDao.dbConnection());
            return cn.connect()
                .then(function () {
                    var req = new sql.Request(cn);
                    var qry = 'select serverproperty(\'productversion\') as \'rs\'';
                    return req.query(qry)
                        .then(function (rs) {
                            qry = 'select isnull(object_id(\'SomeObjectIKnowExists\'), -1)';
                            return req.query(qry)
                                .then(function (rss) { // Note you're not using rss anywhere
                                    return ' CONNECTED// MASTER DB SUCCESS// MY DB SUCCESS';
                                })
                                .catch(function (err) {
                                    return ' CONNECTED// MASTER DB SUCCESS// ISSUE QUERYING MY DB //' + err + '//';
                                });
                        })
                        .catch(function (er) {
                            return ' CONNECTED// COULD NOT QUERY MASTER DB //' + er + '//';
                        });
                })
                .catch(function() {
                    return ' CAN NOT CONNECT';
                });
        }
    };
    

    Note: It IS my intention to NOT use the rej[ect] here. What you see guatanrees only the res[olve] returns. Meaning the code this returns to only needs one path with which to handle the returned value. Thereby the code returned to is simplier in it's flow.

    Rejections follow a separate path from resolutions for a reason. It doesn't make things more complicated, it makes things simpler. Don't convert rejections into resolutions unless you're done an error-recovery of some kind and can continue on as though the rejection hadn't happened.

    Here's that code where rejections are allowed to be rejections:

    var sql = require('mssql');
    var myDao = require('./myDao');
    
    module.exports = {
    
        dbConnection: function () {
            return { user: 'sa', password: 'mypassword', server: 'localhost', database: 'mydb' };
        },
    
        CanIConnectToTheDB: function () {
            var cn = new sql.ConnectionPool(myDao.dbConnection());
            return cn.connect()
                .then(function () {
                    var req = new sql.Request(cn);
                    var qry = 'select serverproperty(\'productversion\') as \'rs\'';
                    return req.query(qry)
                        .then(function (rs) {
                            qry = 'select isnull(object_id(\'SomeObjectIKnowExists\'), -1)';
                            return req.query(qry)
                                .then(function (rss) { // Note you're not using rss anywhere
                                    return ' CONNECTED// MASTER DB SUCCESS// MY DB SUCCESS';
                                });
                        });
                });
        }
    };
    

    Using it:

    theModule.CanIConnectToTheDB()
        .then(function() {
            // Yes, let's do something
        })
        .catch(function() {
            // No, report the problem, etc.
        });
    

    I'd also probably abstract out the bit I assume you'll end up doing over and over: Establishing a connection and getting a request object from it:

    var sql = require('mssql');
    var myDao = require('./myDao');
    
    function getRequest() {
        var cn = new sql.ConnectionPool(myDao.dbConnection());
        return cn.connect().then(function() {
            return new sql.Request(cn);
        });
    }
    
    module.exports = {
    
        dbConnection: function () {
            return { user: 'sa', password: 'mypassword', server: 'localhost', database: 'mydb' };
        },
    
        CanIConnectToTheDB: function () {
            return getRequest().then(function(req) {
                var qry = 'select serverproperty(\'productversion\') as \'rs\'';
                return req.query(qry)
                    .then(function (rs) {
                        qry = 'select isnull(object_id(\'SomeObjectIKnowExists\'), -1)';
                        return req.query(qry)
                            .then(function (rss) { // Note you're not using rss anywhere
                                return ' CONNECTED// MASTER DB SUCCESS// MY DB SUCCESS';
                            });
                    });
            });
        }
    };
    

提交回复
热议问题