Я пытаюсь выполнить итерацию результата запроса MySQL и сделать последующие запросы, чтобы построить мою модель данных. Каждый объект требует нескольких запросов, поэтому я связываю обещания.
Проблема возникает, когда я устанавливаю второй набор обещаний.
Поэтому сначала я получаю список объектов, которые нужно восстановить с помощью g.getSnapshotIds. Затем я перебираю их и использую snapshotId для получения полного моментального снимка.
var gData = {};
g.getSnapshotIds(data.gId, data.userId)
.then(function(value) {
gData = value;
for ( var snapshot in value ) {
var snapshotId = value[snapshot].snapshotId;
var snapshot = {};
g.getSnapshotFull(snapshotId)
.then(function(value) {
console.log(value);
return g.getTs(snapshotId);
})
.then(function(value) {
for ( var te in value ) {
var name = value[te].t;
snapshot[name] = value[te].value;
}
console.log(snapshot);
})
.catch(function(err) {
console.log('Error:', err);
});
}
g.close();
})
.catch(function(err) {
console.log('Error:', err);
});
Я могу вызвать g.getSnapshotFull для каждого ID, но когда я пытаюсь перейти к следующему запросу (g.getTs(snapshotId)), он дает мне ошибку:
Error: Cannot enqueue Query after invoking quit.
Я понятия не имею, почему соединение MySQL закрывается, прежде чем все запросы будут выполнены. Должно ли все внутри цикла for выполняться последовательно, прежде чем двигаться дальше?
Если я прокомментирую g.close(), я не получаю ошибку, но процесс не заканчивается.
Это релевантные методы запросов:
class gDB {
close() {
return new Promise(function(resolve, reject) {
db.end(function(error) {
if ( error ){
reject(new Error(error));
}
// For some reason it is necessary to reestablish this
db = mysql.createConnection({
host: process.env.DBHOST,
user: process.env.DBUSER,
password: process.env.DBPASS,
database: process.env.DBNAME,
ssl: {
ca: fs.readFileSync(__dirname + '/' + process.env.DBCA)
}
});
resolve(true);
});
});
}
getSnapshotIds(gId, uId) {
return new Promise(function(resolve, reject) {
var sql = 'SELECT id AS snapshotId FROM snapshots WHERE gId=' + db.escape(gId) + ' AND uId=' + db.escape(uId) + ' ORDER BY timestamp DESC';
db.query(sql, function (error, results, fields) {
if (error) {
db.destroy();
reject(new Error(error));
} else {
resolve(results);
}
});
});
}
getSnapshotFull(snapshotId) {
return new Promise(function(resolve, reject) {
var sql = 'SELECT s.id AS snapshotId, s.timestamp, s.gId, s.uId, s.clientId FROM snapshots s INNER JOIN controls c ON s.id = c.snapshotId INNER JOIN weathers w ON s.id = w.snapshotId WHERE s.id=' + db.escape(snapshotId);
db.query(sql, function (error, results, fields) {
if (error) {
db.destroy();
reject(new Error(error));
} else {
resolve(results[0]);
}
});
});
}
getTs(snapshotId) {
return new Promise(function(resolve, reject) {
var sql = 'SELECT t.t, st.value FROM snapshots s LEFT JOIN snapshot_t st ON s.id = st.snapshotId INNER JOIN ts t ON st.tId = t.id WHERE s.id=' + db.escape(snapshotId);
db.query(sql, function (error, results, fields) {
if (error) {
db.destroy();
reject(new Error(error));
} else {
resolve(results);
}
});
});
}
Проблема, с которой вы сталкиваетесь, связана с циклами, является синхронной, а обещания асинхронны. Что происходит, вы создаете кучу обещаний, которые ждут чего-то (обещание получить данные), затем цикл for заканчивается (до того, как какое-либо из обещаний закончится), а затем вы вызовете близко. То, что вы хотите сделать, это нечто похожее на нижеследующее.
var gData = {};
g.getSnapshotIds(data.gId, data.userId)
.then(function (value) {
gData = value;
var promises = [];
for (var snapshot in value) {
var snapshotId = value[snapshot].snapshotId;
var snapshot = {};
var promise = g.getSnapshotFull(snapshotId)
.then(function (value) {
console.log(value);
return g.getTs(snapshotId);
})
.then(function (value) {
for (var te in value) {
var name = value[te].t;
snapshot[name] = value[te].value;
}
console.log(snapshot);
});
promises.push(promise);
}
return Promise.all(promises);
})
.then(function (values) {
g.close();
console.log(values);
})
.catch(function (err) {
console.log('Error:', err);
});
То, что решает это, спасает обещание, а затем использует Promise.all(promises)
чтобы ждать выполнения всех обещаний. Последний блок будет иметь результаты всех обещаний, и вы можете закрыть соединение с базой данных.