Mettre à jour
Voir la modification ci-dessous pour la syntaxe async/wait
J'ai passé du temps à écrire une version généralisée de l'exemple de transaction donné par node mysql, alors j'ai pensé le partager ici. J'utilise Bluebird comme bibliothèque de promesses et je l'ai utilisée pour "promisifier" l'objet de connexion, ce qui a beaucoup simplifié la logique asynchrone.
const Promise = ('bluebird');
const mysql = ('mysql');
/**
* Run multiple queries on the database using a transaction. A list of SQL queries
* should be provided, along with a list of values to inject into the queries.
* @param {array} queries An array of mysql queries. These can contain `?`s
* which will be replaced with values in `queryValues`.
* @param {array} queryValues An array of arrays that is the same length as `queries`.
* Each array in `queryValues` should contain values to
* replace the `?`s in the corresponding query in `queries`.
* If a query has no `?`s, an empty array should be provided.
* @return {Promise} A Promise that is fulfilled with an array of the
* results of the passed in queries. The results in the
* returned array are at respective positions to the
* provided queries.
*/
function transaction(queries, queryValues) {
if (queries.length !== queryValues.length) {
return Promise.reject(
'Number of provided queries did not match the number of provided query values arrays'
)
}
const connection = mysql.createConnection(databaseConfigs);
Promise.promisifyAll(connection);
return connection.connectAsync()
.then(connection.beginTransactionAsync())
.then(() => {
const queryPromises = [];
queries.forEach((query, index) => {
queryPromises.push(connection.queryAsync(query, queryValues[index]));
});
return Promise.all(queryPromises);
})
.then(results => {
return connection.commitAsync()
.then(connection.endAsync())
.then(() => {
return results;
});
})
.catch(err => {
return connection.rollbackAsync()
.then(connection.endAsync())
.then(() => {
return Promise.reject(err);
});
});
}
Si vous vouliez utiliser la mise en commun comme vous l'avez suggéré dans la question, vous pouvez facilement changer le createConnection
ligne avec myPool.getConnection(...)
, et changez le connection.end
lignes avec connection.release()
.
Modifier
J'ai fait une autre itération du code en utilisant le mysql2
bibliothèque (même api que mysql
mais avec le support de la promesse) et les nouveaux opérateurs async/wait. Voilà
const mysql = require('mysql2/promise')
/** See documentation from original answer */
async function transaction(queries, queryValues) {
if (queries.length !== queryValues.length) {
return Promise.reject(
'Number of provided queries did not match the number of provided query values arrays'
)
}
const connection = await mysql.createConnection(databaseConfigs)
try {
await connection.beginTransaction()
const queryPromises = []
queries.forEach((query, index) => {
queryPromises.push(connection.query(query, queryValues[index]))
})
const results = await Promise.all(queryPromises)
await connection.commit()
await connection.end()
return results
} catch (err) {
await connection.rollback()
await connection.end()
return Promise.reject(err)
}
}