webentwicklung-frage-antwort-db.com.de

Javascript, um mehrere Versprechen abzuwarten

Was ich erreichen möchte:

  • künstler-IDs sammeln
    • entweder sie in der DB finden
    • oder sie schaffen
  • erstellen eines Ereignisses in der Datenbank, Abrufen der Ereignis-ID
  • warten, bis beide fertig sind, Künstler und Event-IDs gesammelt
  • jetzt über den Künstler, Event-Kombinationen

Was ich bekam:

Ich arbeite mit Node und MySQL. Um die Beziehungen einzufügen, muss ich warten, bis die Künstler eingefügt oder erstellt werden. Ich versuche mit folgendem Code zu erreichen:

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);

Rückgabe einer ID:

async function find_artist_id_or_create_new_artist(artist_name) {
    return await find_artist_return_id(artist_name, create_artist_return_id)
} 

Einen Künstler finden:

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
      }
    });
}

Einen Künstler erstellen

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
    });
}

Ich verstehe, dass ich nicht in einer con.query-Funktion zurückkehren kann, aber ich kann nicht den Code richtig einrichten, um dies zu erreichen. Ein Link zu oder eine Hilfe bei der Suche nach einer Antwort wird gebeten.

8
bart great

Ihr SQL functions muss in promises konvertiert werden, um awaited zu sein.

Siehe Async Function , Promise und Array.prototype.map() für weitere Informationen.

// 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)
}))
3
Arman Charan

Sie müssen nur die mysql-Callbacks in Versprechungen einschließen:

 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);      
      });
   });
}

Und das ist übrigens sehr hässlich:

 if (artists.length != 0) {
   for (key in artists) {

Mach einfach:

  for(const artist of artists)
    promises.Push(someApiCall(artist));

oder:

  const promises = artists.map(someApiCall);
0
Jonas Wilms

Der einfache Weg ist die Verwendung bereits vorhandenerORMlike sequalizejs oder etc. Sie geben ein Versprechen für Sie ab und führen stattdessen find und create in einer separaten Raw-Abfrage im nativen MySQL-Treiber aus. Sie können APIs einfach wie Suchen oder Erstellen von etwas verwenden.

ich erkläre Ihnen, wie Async in Ihrem Beispiel funktioniert. Ich habe einen Code aus Ihrem Beispiel genommen.

    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');
})();

schaue in createArtist function das ist genau das, was du hast. Drei Dinge, die Sie hier beachten müssen,

  1. sie deklarieren es als asynchrone Funktion, so dass Sie das Versprechen als Standardwert zurückgeben.
  2. es kann einfach eine normale Funktion zurückgegeben werden, wenn es sich um eine synchrone Funktion handelt, vermeiden Sie die Verwendung von asynchron.
  3. Wie Sie sagten, können Sie nichts vom Rückruf zurückgeben. da es asynchron ist, müssen Sie das Versprechen zurückgeben.

so kann der Code in geändert werden

    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');
})();

Hier haben sich die Dinge geändert, ein nativer Versprecher hinzugefügt und zurückgegeben, bevor er asynchron läuft. Entschlossenheit genannt, um Erfolg zu haben. Und lehne es ab, um es zum Scheitern zu bringen.

Vergiss nicht, try ... catch blog hinzuzufügen, um den Fehler zu behandeln.

0
Vignesh