Задать вопрос
@a1en_yeah

Передача значений во внешний promise из внутреннего, как это реализовать (nodeJS,ExpressJS)?

Добрый день,
у меня есть клиент на ангуляре, и сервер на nodeJS.
При обращении к /home/allservers я надеюсь получить список серверов, в форме массива из объектов,
каждый сервер имеет хост, и кластеры внутри, в свою очередь кластеры имеют массив баз данных. Вообщем каждый сервер из массива выглядит примерно так:
{
  "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:user@10.0.1.1:5432/DBAUDIT")
С этой частью всё гуд, вообщем выполняем 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);

    })
    
};


И в итоге я вижу в консоле поочередно выведенные сервера, и могу допустим возвратить список кластеров , но как мне возвратить список серверов я ума не приложу, куда положить servers.push(server); и в итоге вывести его вместо кластеров (resolve(clusters); )
Внутренний промис не видит списка кластеров, и не resolv-ит наружу сервера поодиночке, а внешний, не видит моих объектов server...
Голова уже не варит, а время идёт, может сможете подсказать решение задачки ?
  • Вопрос задан
  • 421 просмотр
Подписаться 1 Оценить 1 комментарий
Пригласить эксперта
Ответы на вопрос 2
@napa3um
Промисы можно вкладывать друг в друга путём возврата нового промиса из обработчика then (если я правильно понял проблему, покажу на примере):

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));
Ответ написан
@VitalyT
Пример того как это решается при помощи обычных запросов с промисами: stackoverflow.com/questions/37664258/get-a-parents...
Ответ написан
Ваш ответ на вопрос

Войдите, чтобы написать ответ

Похожие вопросы