A
A
a1en_yeah2016-07-12 16:48:00
JavaScript
a1en_yeah, 2016-07-12 16:48:00

Passing values ​​to an outer promise from an inner one, how to implement it (nodeJS, ExpressJS)?

Hello,
I have an Angular client and a nodeJS server.
When accessing /home/allservers I hope to get a list of servers, in the form of an array of objects,
each server has a host, and the clusters inside, in turn the clusters have an array of databases. In general, each server from the array looks something like this:

{
  "host": "10.8.37.124",
  "clusters": [
    {
      "name": "postgresql-9.3",
      "version": "9.3.9",
      "port": 5433,
      "databases": [ "totodb"]
    },
    {
      "name": "postgresql-9.4",
      "version": "9.4.4",
      "port": 5432,
      "databases": [
        "testdb",
        "benchdb",
        "repmgr"
      ]
    }
  ]
}

home.js
app.get('/home/allservers', function(request, response) {
    logger.info(request.user.uid + ' request all servers from DB_Audit');
    dbAudit.getAllServers()
    .then(function(servers) {
      response.json(servers);
    }, function(error) {
      logger.error('failed to get all servers', error);
    });
  });

(dbAudit = "dbAudit": "postgres://user:[email protected]:5432/DBAUDIT")
Everything is good with this part, in general we execute getAllServers()
dbAudit.js
dbAudit.query = function(query) {
    return new Promise(function(resolve, reject) {
        sequelize.query(query)
        .spread(resolve , function(error) {
            logger.error('Failed to query dbAudit:' + query, error); 
        }, reject);
    });
};

dbAudit.getAllServers = function() {
    return new Promise(function(resolve, reject) {

        //get all clusters
        dbAudit.query(
            'SELECT '
            +   '"FQDN" AS host, '
            +   '"Listen_Port" AS port, '
            +   '"Instance" AS "clusterName", '
            +   '"Version" AS version '
            +   'FROM "COLLECTE_POSTGRES"'
            +   'WHERE ("FQDN" LIKE \'p%\') '
            +   'AND ("FQDN" NOT lIKE \'pgstore%\');'
        ).then(function(clusters) { 
            var servers = []; // Вот мы получили от базы данных список кластеров, и здесь я создаю свой пустой массив для списка серверов
            clusters.forEach(function(cluster) {
                // обходим тут каждый кластер из списка, при этом создаем новое подключение через Sequelize
               //  и получаем список баз данных на каждом из них
  
                var remote = new Sequelize('postgres', collector.user, collector.password, {host: cluster.host, port: cluster.port, dialect: 'postgres', logging: false});
                remote.query("SELECT datname FROM pg_catalog.pg_database WHERE datname NOT IN ('template0','template1','postgres','repmgr')")
                .then(function(databases) {
                   // получаем список баз данных на одном из кластеров достаточно в неприяглядной форме, поэтому 
                   // дальше его преобразовываем, и вставляем сначала в кластеры, потом в сервер
                   // dbs это массив из имён баз
                   // cluster это  объект с 4 свойствами (port, version, databases, name)
                   // clusters это массив объектов cluster
                   // server это объект с 2 свойствами: host и  clusters
                    var server = {};
                     var dbs = [];

                     var newdb = function(db){
                        for (var i=0;i<db.length;i++){
                            dbs.push(db[i].datname);
                        }
                     };
                     newdb(databases);
                    cluster.databases = dbs;
                    cluster.name = cluster.clusterName;

                    var server = {};
                    server.host = cluster.host;
                    delete cluster.host;
                    delete cluster.clusterName;
                    server.clusters = [];
                    server.clusters.push(cluster);
                    console.log(server);
                   // вот тут я для проверки вывожу поочердно каждый сервер, и всё достаточно хорошо
                }, function(error) {
            logger.error('failed to get databases from clusters', error);
                                    }
                    )
            });
        resolve(clusters); // тут я спокойненько возвращаю на обработчик, а далее клиенту, список кластеров
        },reject);

    })
    
};

And in the end, I see in the console the servers displayed one by one, and I can, for example, return a list of clusters, but I don’t know how to return a list of servers, where to put servers.push(server); and eventually display it instead of clusters (resolve(clusters); )
The internal promise does not see the list of clusters, and does not resolv-it outside the server one by one, but the external one does not see my server objects ...
The head no longer boils, but time goes by, can you suggest a solution to the problem?

Answer the question

In order to leave comments, you need to log in

2 answer(s)
N
napa3um, 2016-07-12
@napa3um

Promises can be nested into each other by returning a new promise from the then handler (if I understand the problem correctly, I will show it with an example):

new Promise((resolve, reject) => {
    setTimeout(() => {
        console.log('операция 1');
        resolve({ op1: true }); /* data for next handler */
    }, 1000);
})
.then(data => {
    return new Promise((resolve, reject) => {
        setTimeout(() => {
            console.log('операция 2');
            data.op2 = true; /* update data */
            resolve(data);
        }, 1000);
    })
})
.then(data => console.log('операция 1 и 2 выполнены', data)) /* { op1: true, op2: true } */
.catch(err => console.log('ошибка в операции 1 или 2', err));

V
VitalyT, 2016-07-19
@VitalyT

An example of how this can be done with normal requests with promises: stackoverflow.com/questions/37664258/get-a-parents...

Didn't find what you were looking for?

Ask your question

Ask a Question

731 491 924 answers to any question