【问题标题】:Testing a Promise within another Promise's .then()在另一个 Promise 的 .then() 中测试一个 Promise
【发布时间】:2017-07-31 20:06:03
【问题描述】:

我正在尝试了解如何在另一个 Promise 中解决一个 Promise。
我希望实现的步骤如下:

  1. 通过UserManager(功能)通过其ID获取User
  2. 更改其firstName
  3. 通过UserManagerUser保存到数据库中(功能)

我正在测试UserManager.saveUser(user); 的响应,它在成功时返回true。但我遇到了一个错误。


UserManagerTest.js

//[...]

it("Should save a user to the database", function () {
    var response = UserManager.getUserByLogin("Foo.Bar@provider.com", "Test")
        .then(function (user) {
            user.firstName = "Macarena";
            return UserManager.saveUser(user);
        })
        .catch((error) => {
            console.log("This error occured: "+error);
            return false;
        })
    return Promise.all([
        expect(response).to.eventually.be.true
    ]);
});

//[...]

控制台输出

  1) UserManager Save Should save a user to the database:
     AssertionError: expected undefined to be true
      at node_modules/chai-as-promised/lib/chai-as-promised.js:305:22
      at process._tickCallback (internal/process/next_tick.js:109:7)

UserManager.js

static saveUser(user){
    return new Promise((resolve, reject) => {
        pool.getConnection((err, connection)=> {
            if(err) reject(err);

            connection.query("SHOW COLUMNS FROM User;", (error, results, fields) => {
                if(error) reject(error);

                var availableFields = {savable: [], primary: []};
                //[...]
                resolve(availableFields);
            });

            connection.release();
        });
    })
    .then((result) => {
        var usedFields = {savable: [], primary: []};
        //[...]
        return usedFields;
    })
    .then((result) => {
        var sqlParams = [];
        var sql = "UPDATE User SET";
        //[...]
        sql += ";";
        pool.getConnection((err, connection) => {
            if(err) throw err;

            connection.query(sql, sqlParams, (error, results, fields) => {
                if(error) throw error;
                connection.release();
                return results.affectedRows == 1;
            });
        });
    })
    .catch((error) => {
        console.log(error);
        throw error;
    })
};

【问题讨论】:

  • 在这里猜测,但是,如果你的 connection.release();在connection.query里面?似乎您可以在获得结果之前释放连接。我没有看到其他对我来说很突出的东西。
  • 根据documentation,您是对的,但这不会改变问题。在return 语句之前添加console.log(results.affectedRows); 会显示正确的结果。并测试此函数是否正确更新了数据库中的值。
  • 不是原因,而是 FWIW:if(err) reject(err); 将继续运行其余代码(并且可能会导致 connection.query() 抛出错误);一旦你拒绝了承诺,请使用return 来防止这种情况(或使用if (err) return reject(err)

标签: javascript node.js promise mocha.js chai


【解决方案1】:

第二个then((result)=> ...) 不返回任何内容,因此undefined

return results.affectedRows == 1; 在 lambda 中。它返回那个 lambda,而不是周围的 `then``

您需要更改pool.getConnection 的语义以将其从回调更改为Promise。将它包装在一个 Promise 中,解决它并链接它,看起来像

return new Promise((resolve, reject) => {

    pool.getConnection((err, connection) => {
        if(err) {
             //see @robertklep comment
             try { connection.release(); } catch(e) { /* ignore ? */ }
             return reject(err);
        }

        connection.query(sql, sqlParams, (error, results, fields) => {
            if(error) throw error;
            connection.release();
            resolve(results.affectedRows == 1);
        });
    });
})

【讨论】:

  • reject(err); 需要 return 语句而 resolve(boolean); 不需要的原因吗?
  • 你应该在抛出错误之前释放连接。
  • @faegy return 只是为了立即退出承诺 lambda;它实际上并没有返回任何感兴趣的东西。但在这样做之前,您应该按照@robertklep 的建议释放连接
【解决方案2】:

MySql 是异步的,不返回承诺。

function queryDB(result) {
  return new Promise((resolve, reject) => {
        var sqlParams = [];
        var sql = "UPDATE User SET";
        //[...]
        sql += ";";
        pool.getConnection((err, connection) => {
            if(err) {
                reject(err);
                return connection.release();
            }

            connection.query(sql, sqlParams, (error, results, fields) => {
                if(error) ? reject(error) : resolve(results.affectedRows == 1);
                connection.release();
            });
        });
  })
}

【讨论】:

  • 请参阅my comment 关于拒绝后返回 :) 另外,返回之前释放连接,否则你最终会得到一个空池。
  • 非常正确,我对这个问题的看法是狭隘的,而不是其他问题。 ;) 但是,拒绝/解决不返回。这段代码显然需要测试。
猜你喜欢
  • 2023-03-31
  • 2021-09-09
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2019-09-17
  • 1970-01-01
  • 1970-01-01
  • 2019-08-03
相关资源
最近更新 更多