首页 > 解决方案 > Promise.all 不等待嵌套的承诺?

问题描述

我是 Promises 的新手,无法理解它们是如何工作的。我有一个 MySQL 语句列表,我想在返回它们的值之前完成。我尝试使用Promise.all将每个语句添加为 Promise,但从Promise.all不等待嵌套的 Promise 完成。关于 SO 的类似问题有类似也不返回 Promises 的问题,这不是我的问题。如果有人可以提供指导,我保证我会非常感激。

class Database {
    constructor( config ) {
        this.connection = mysql.createConnection( config );
    }
    query( sql, args ) {
        return new Promise( ( resolve, reject ) => {
            this.connection.query( sql, args, ( err, rows ) => {
                if ( err )
                    return reject( err );
                resolve( rows );
            } );
        } );
    }
    close() {
        return new Promise( ( resolve, reject ) => {
            this.connection.end( err => {
                if ( err )
                    return reject( err );
                resolve();
            } );
        } );
    }
}

function scanCountWrapper(resname, resProjectDict){
  var sql = "SELECT COUNT(*) FROM table WHERE resource = '" + resname + "'";
  database.query(sql).then( count => {  // query returns a Promise (see above function definition)
    return new Promise((resolve) => { // nested promise
      resProjectDict[resname] = count[0]["COUNT(*)"];
      resolve(count[0]["COUNT(*)"]);
    })
  })
}

function getAnyCount(latestResourceList, cb){
  var resProjectDict = {};
  var scanPromises = [];
  for (r=0;r<latestResourceList.length;r++){
      var resname = latestResourceList[r];
      console.log("resource is " + resname);
      scanPromises.push(scanCountWrapper(resname, resProjectDict)); //add Promise
  }
  Promise.all(scanPromises)
    .then((values) => { // this doesn't wait for the nested promises to finish executing
      console.log(resProjectDict); // EMPTY because nested promises have not exeecuted.
    })
}

编辑

抱歉忘了提查询也返回了一个承诺(我在上面添加了该功能)

标签: javascriptpromise

解决方案


您正在从 传递给Promise.all()返回值数组scanCountWrapper()。但scanCountWrapper()不返回任何内容,因此您只是传递值Promise.all()数组undefined

相反,您需要向它传递一系列承诺。因此,scanCountWrapper()需要返回一个连接到其中的异步操作的 Promise。

您可以通过更改database.query(...).then(...)return database.query(...).then(...)

function scanCountWrapper(resname, resProjectDict){
  var sql = "SELECT COUNT(*) FROM table WHERE resource = '" + resname + "'";
  return database.query(sql).then( count => {
      resProjectDict[resname] = count[0]["COUNT(*)"];
      return count[0]["COUNT(*)"];
  });
}

此外,您在.then()处理程序内部创建的承诺是不必要的。您可以直接从.then()处理程序返回一个值,该值将成为父 Promise 链的解析值。


推荐阅读