Javascript, how to await multiple promises

This question already has an answer here:

  • How do I convert an existing callback API to promises? 17 answers

  • Your fundamental SQL functions need to be converted to promises in order to be awaited .

    See Async Function , Promise and Array.prototype.map() for more info.

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

    You just need to wrap the mysql callbacks into promises:

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

    And by the way, this is very ugly:

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

    Just do:

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

    or:

      const promises = artists.map(someApiCall);
    

    The Easy way is to use already existing ORM like sequalizejs or etc they return promise for you and instead of running find and create in separate Raw query in native MySQL driver. You can simply use API'S like find or create something.

    i explain you how async works in your example , i took a piece of code from your example.

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

    look into createArtist function this is exactly what you have . Three things you have to note here,

  • you declare it a async function so it return promise in default.
  • it can simply return anything like normal function ,if it is a synchronous function avoid using async.
  • As you said you cannot return anything from callback . since it is asynchronous you have to return promise.
  • so the code can be changed to

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

    Things changed here , added native promise wrapper and return it, before it goes asynchronous. called resolve to make success . And reject to make it fail.

    Don't forget to add try ...catch blog for await's to handle error.

    链接地址: http://www.djcxy.com/p/55536.html

    上一篇: 承诺如何在这种情况下实施?

    下一篇: Javascript,如何等待多重承诺