Estoy tratando de entender cómo resolver una promesa dentro de otra promesa.
Los pasos que estoy buscando lograr son los siguientes:

  1. Obtenga un User por su ID a través del UserManager (Funcionamiento)
  2. Altera su firstName
  3. Guarde el User en la base de datos a través del UserManager (en funcionamiento)

Estoy buscando probar la respuesta de UserManager.saveUser(user); que devuelve true en caso de éxito. Pero recibo un error.


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

//[...]

Salida de la consola

  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;
    })
};
3
Faegy 10 mar. 2017 a las 16:01

2 respuestas

La mejor respuesta

El segundo then((result)=> ...) no devuelve nada, por lo tanto, el undefined

El return results.affectedRows == 1; está dentro de una lambda. Regresa en esa lambda, no en el `entonces` circundante

Debe cambiar la semántica de pool.getConnection para cambiarla de una devolución de llamada a una Promesa. Envuélvala en una promesa, resuélvala y encadénela, algo que parece

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);
        });
    });
})
5
Bruno Grieder 10 mar. 2017 a las 14:04

MySql es asíncrono y no devuelve una promesa.

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();
            });
        });
  })
}
0
Michael Hobbs 10 mar. 2017 a las 13:58