Welcome to OGeek Q&A Community for programmer and developer-Open, Learning and Share
Welcome To Ask or Share your Answers For Others

Categories

0 votes
223 views
in Technique[技术] by (71.8m points)

javascript - node.js ~ constructing chained sequence of Promise resolves

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 events.

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.

It might help to know, if you don't recognize it, this is taken from a module I created. Think of it as a Dao.

module.exports = {

    dbConnection: function () {
        return { user: 'sa', password: 'mypassword', server: 'localhost', database: 'mydb' };
    },


    CanIConnectToTheDB: function () {
        return new Promise(function (res, rej) {
            var sql = require('mssql');
            var myDao = require('./myDao');
            var cn = new sql.ConnectionPool(myDao.dbConnection());

            cn.connect().then(function () {
                var req = new sql.Request(cn);
                var qry = 'select serverproperty('productversion') as 'rs'';
                req.query(qry)
                    .then(function (rs) {
                        qry = 'select isnull(object_id('SomeObjectIKnowExists'), -1)';
                        req.query(qry)
                            .then(function (rss) {
                                res(' CONNECTED// MASTER DB SUCCESS// MY DB SUCCESS');
                            })
                            .catch(function (err) {
                                res(' CONNECTED// MASTER DB SUCCESS// ISSUE QUERYING MY DB //' + err + '//');
                            });
                    })
                    .catch(function (er) {
                        res(' CONNECTED// COULD NOT QUERY MASTER DB //' + er + '//');
                    });
            })
            .catch(function () {
                res(' CAN NOT CONNECT');
            });
        });
    }
};
See Question&Answers more detail:os

与恶龙缠斗过久,自身亦成为恶龙;凝视深渊过久,深渊将回以凝视…
Welcome To Ask or Share your Answers For Others

1 Reply

0 votes
by (71.8m points)

Instead of something like this:

                .then(function (rs) {
                    qry = '...';
                    req.query(qry)
                        .then(function (rss) {

you can use something like this:

                .then(function (rs) {
                    qry = '...';
                    return req.query(qry);
                }).then(function (rss) {

I.e. you can return a promise in one then callback and get the resolved value of that promise in the next then callback, so your indentation keeps constant.

Simpler example - instead of this:

a().then(va => {
    b(va).then(vb => {
        c(vb).then(vc => {
            // you can use vc here
        });
    });
});

you can do:

a().then(va => {
    return b(va);
}).then(vb => {
    return c(vb);
}).then(vc => {
    // you can use vc here
});

Or, even simpler if you use async and await:

va = await a();
vb = await b(va);
vc = await c(vb);
// you can use vc here

Note that you can only use await inside of a function created with the async keyword. In places where you don't have native support for async and await you can use Babel or with a slightly different syntax a generator based approach like in co or Bluebird coroutines. For more info and support in browsers and Node, see this answer:

Update

This is not tested, but this is more or less how I would write it:

module.exports = {

    dbConnection: function () {
        return { user: 'sa', password: 'mypassword', server: 'localhost', database: 'mydb' };
    },

    CanIConnectToTheDB: function () {
        var sql = require('mssql');
        var myDao = require('./myDao');
        var cn = new sql.ConnectionPool(myDao.dbConnection());
        var req;

        return cn.connect()
        .catch(err => Promise.reject('Error 1: ' + err))
        .then(() => {
            req = new sql.Request(cn);
            var qry = 'select serverproperty('productversion') as 'rs'';
            return req.query(qry)
                .catch(err => Promise.reject('Error 2: ' + err));
        }).then(rs => {
            var qry = 'select isnull(object_id('SomeObjectIKnowExists'), -1)';
            return req.query(qry)
                .catch(err => Promise.reject('Error 3: ' + err));
        }).then(function (rss) {
            return 'CONNECTED// MASTER DB SUCCESS// MY DB SUCCESS';
        }).catch(err => {
            // if you want it always resolved:
            return 'CAN NOT CONNECT: ' + err;
        });
    }
};

Of course I would keep the final promise returned by that function to be rejected on errors and resolved only on success, but since you explicitly included that strange requirement in your question then I wrote it how you wanted.

But if it rejected the promise on any error then it would be much easier to use, especially if all you care is the answer to the question in the name of the function - Can I Connect To The DB:

CanIConnectToTheDB()
    .then(() => console.log("Yes I can"))
    .catch(() => console.log("No I can't"));

More info:

For more info see those answers:


与恶龙缠斗过久,自身亦成为恶龙;凝视深渊过久,深渊将回以凝视…
OGeek|极客中国-欢迎来到极客的世界,一个免费开放的程序员编程交流平台!开放,进步,分享!让技术改变生活,让极客改变未来! Welcome to OGeek Q&A Community for programmer and developer-Open, Learning and Share
Click Here to Ask a Question

...