正确使用承诺来返回结果

时间:2015-01-27 23:36:46

标签: javascript promise

我正在使用the 'Q' library作为承诺。

以下是该方案:

var results = dbContext.query(userCert.conn, dbQuery.BuildQuery(query));

var models = [];
if (!results.hasErr) {
    for (var r in results.okPacket.results) {
        var m = new model(results.okPacket.results[r]);
        models.push(m);
    }
}
userCert.conn.end(); // close db connection

dbContext.query(...)

var $Q = require('Q');

function execQuery(connection, query) {
    console.log("[backend][context] EXEC QUERY: " + query);
    $Q.nfcall(connection.query, query)
        .then(function (err, results) {
            var ret = {};
            if (err) {
                // log
                var errPkt = getErrPacket(err);
                console.log("QUERY ERROR[" + errPkt.errCode + ": " +
                errPkt.errConst + "]: " + errPkt.errMessage);
                ret = {
                    hasErr: true,
                    errPacket: errPkt
                };
            } else {
                ret = {
                    hasErr: false,
                    okPacket: {
                        resType: results.constructor.name,
                        resLength: results.length,
                        results: results
                    }
                };
            }

            // is this correct?
            return function () {
                return ret;
            };
        })
        .then(function (ret) {
            // how do I then return ret to the caller?
        })
        .done();
}

我只是有点迷失方向(如果可能的话)。在我的应用程序的较低级别回调是可以的,但我不想最终得到一个充满回调意大利面的菜。

2 个答案:

答案 0 :(得分:2)

通过承诺,您只需将承诺退还给来电者:

function execQuery(connection, query) {
    console.log("[backend][context] EXEC QUERY: " + query);
    return $Q.nfcall(connection.query, query)
        .then(function(results) {
            return {
                hasErr: false,
                okPacket: {
                    resType: results.constructor.name,
                    resLength: results.length,
                    results: results
                }   
            };
        })
        .catch(function(err) {
            // This doesn't necessarily mean a database error because
            // all errors are caught here
            if (false /*
                TODO logic that checks if the err is not a database error
                in which case you should just rethrow
            */) {
                throw err;
            }
            var errPkt = getErrPacket(err);
            console.log("QUERY ERROR[" + errPkt.errCode + ": " +
            errPkt.errConst + "]: " + errPkt.errMessage);
            return {
                hasErr: true,
                errPacket: errPkt
            };
        });
}

然后调用者可以使用返回的promise:

dbContext.query(userCert.conn, dbQuery.BuildQuery(query))
    .then(function(results) {
        // It is really weird to have to check for error in the success
        // case but whatever floats your boat
        if (!results.hasErr) {
            var models = results.okPacket.results.map(function(result) {
                return new model(result);
            });
        }
    })
    .finally(function() {
        userCert.conn.end();
    })
    .done();

答案 1 :(得分:0)

承诺仍然是回调。它们不会改变代码的实际机制。唯一的区别是promises允许你取消嵌套回调。但你还在使用回调:

// regular callbacks:
do_something(function(x){
    do_something_else(function(y){
        do_last_thing();
    });
});

// with promises:
do_something()
.then(function(x){
    do_something_else();
})
.then(function(y){
    do_last_thing();
});

您无法将值返回给调用者,因为代码是异步运行的。与promises的唯一区别是,不是传递IN回调,而是返回一个对象(promise),它有一个名为then的方法,你传递回调。