Ce que je veux accomplir:
Ce que j'ai:
Je travaille avec Node et mysql. Pour insérer les relations, je dois attendre que les artistes insèrent ou créent. J'essaie d'accomplir avec le code suivant:
let promises = [];
if (artists.length != 0) {
for (key in artists) {
promises.Push( find_artist_id_or_create_new_artist(artists[key]) )
}
}
await Promise.all(promises);
Renvoyer un identifiant:
async function find_artist_id_or_create_new_artist(artist_name) {
return await find_artist_return_id(artist_name, create_artist_return_id)
}
Trouver un artiste:
async function find_artist_return_id(artist_name, callback) {
var sql = "SELECT * FROM `artists` WHERE `name` LIKE "+con.escape(artist_name)+" LIMIT 1;"
con.query(sql, (err,row) => {
if(err) throw err;
if (row.length == 0) {
return callback(artist_name)
} else {
return row[0].id
}
});
}
Créer un artiste
async function create_artist_return_id(artist_name) {
var sql = "INSERT INTO `artists` (`id`, `name`, `meta_1`, `meta_2`) VALUES (NULL, "+con.escape(artist_name)+", NULL, NULL)";
con.query(sql, (err, result) => {
if(err) throw err;
return result.insertId
});
}
Je comprends que je ne peux pas revenir dans une fonction con.query, mais je ne sais pas comment configurer correctement le code pour que cela soit fait. Un lien vers ou une aide pour rechercher une réponse est apprécié.
Votre SQL functions
fondamental doit être converti en promises
pour être awaited
.
Voir Async Function
, Promise
et Array.prototype.map()
pour plus d'informations.
// Artist Ids.
const artistIds = await Promise.all(artists.map(async (artist) => await findArtist(artist) || await createArtist(artist)))
// Find Artist.
const findArtist = artist => new Promise((resolve, reject) => con.query(`SELECT * FROM \`artists\` WHERE \`name\` LIKE ${con.escape(artist)} LIMIT 1;`, async (error, row) => {
if(error) return reject(error)
if (!row.length) return resolve(await createArtist(artist))
return resolve(row[0].id)
}))
// Create Artist.
const createArtist = artist => new Promise((resolve, reject) => con.query(`INSERT INTO \`artists\` (\`id\`, \`name\`, \`meta_1\`, \`meta_2\`) VALUES (NULL, ${con.escape(artist)}, NULL, NULL)`, (error, result) => {
if (error) return reject(error)
return resolve(result.insertId)
}))
Vous devez juste envelopper les rappels mysql dans des promesses:
function find_artist_return_id(artist_name) {
return new Promise((resolve, reject) => {
var sql = "SELECT * FROM `artists` WHERE `name` LIKE "+con.escape(artist_name)+" LIMIT 1;"
con.query(sql, (err,row) => {
if(err) return reject(err);
if (row.length == 0) {
return resolve(artist_name);
return resolve(row[0].id);
});
});
}
Et au fait, c'est très moche:
if (artists.length != 0) {
for (key in artists) {
Il suffit de faire:
for(const artist of artists)
promises.Push(someApiCall(artist));
ou:
const promises = artists.map(someApiCall);
La méthode la plus simple consiste à utiliser les commandes déjà existantesORMlike sequalizejs ou etc, car elles vous renvoient des promesses et au lieu de rechercher et créer dans une requête Raw séparée dans le pilote MySQL natif. Vous pouvez simplement utiliser les API comme trouver ou créer quelque chose.
je vous explique comment async fonctionne dans votre exemple, j'ai pris un morceau de code de votre exemple.
async function createArtist(artist_name) {
var sql = "INSERT INTO `artists` (`id`, `name`, `meta_1`, `meta_2`) VALUES (NULL, "+con.escape(artist_name)+", NULL, NULL)";
con.query(sql, (err, result) => {
if(err) throw err;
return result.insertId
});
}
const artistId = (async () => {
await createArtist('maxi');
})();
regardez dans createArtist function c'est exactement ce que vous avez. Trois choses que vous devez noter ici,
de sorte que le code peut être changé pour
async function createArtist(artist_name) {
return new Promise((resolve,reject)=>{
var sql = "INSERT INTO `artists` (`id`, `name`, `meta_1`, `meta_2`) VALUES (NULL, "+con.escape(artist_name)+", NULL, NULL)";
con.query(sql, (err, result) => {
if(err) reject(err);
resolve(result.insertId)
});
});
}
const artistId = (async () => {
await createArtist('maxi');
})();
Les choses ont changé ici, ajouté un wrapper natif de promesse et le retourne avant qu'il ne devienne asynchrone. appelé résoudre pour réussir. Et rejeter pour le faire échouer.
N'oubliez pas d'ajouter try ... catch blog for wait's pour gérer les erreurs.