问.js,承诺,类和"this",上下文是什么?



我完全搞不懂Q promise里面的上下文。我不认为这是Q特有的,但所有的承诺都是通用的。this在类中的上下文到底是什么?

这段代码使用TypeScript,现在一切都是静态的,因为我基本上失败了做任何非静态的事情。这段代码运行良好。

我尝试添加一个private _config;实例变量,并使用_getConfig方法在构造函数中设置_config。但是,当我在方法checkMongodbConnection中使用this._config时,它与_getConfig()方法返回的对象不同。(我在调试模式下观察变量状态)

所以我猜this,在一个类中,因为我从一个Q承诺调用代码,没有类实例上下文。

我想知道如果使用承诺是一个好主意毕竟,如果我遇到上下文问题的代码将只是很多更难以理解和调试。我希望你能理解我的原因并做出相应的选择。我不想丢失类实例上下文,那太棘手了。我害怕使用一种实际上会使事情变得更复杂的技术,我更喜欢回调地狱

///<reference path='./def/defLoader.d.ts'/>    
export class App {
    /**
     * Constructor.
     * Load the config.
     * @return {}
     */
    private static _getConfig(){
        if(typeof __config !== "undefined"){
            return __config;
        }else{
            require('./../../shared/lib/globals/services');
            return configHelper.load('_serverConfig', require('./../../shared/config/_serverConfig.json').path.config, __dirname + '/../../');
        }
    }
    /**
     * Check that the mongoose connection open correctly, meaning that the mongod process is running on the host.
     * @return {Q.Promise<T>|Function}
     */
    public static checkMongodbConnection(){
        var config = App._getConfig();
        // Building promise
        var deferred: any = Q.defer();
        if(config.game.checkMongodb){
            // Retrieves the mongoose configuration file, the env doesn't matter here.
            var mongodbConfig = require('./../../shared/config/mongodb.json')['development'];
            // Try mongoose connexion
            mongoose.connect('mongodb://' + mongodbConfig.host + '/' + mongodbConfig.database);
            // Bind connexion
            var db: mongoose.Connection = mongoose.connection;
            // Get errors
            db.on('error', function(err) {
                deferred.reject('Mongodb is not running, please run the mongod process: n' + err)
            });
            // If the connexion seems to be open
            db.once('open', function callback () {
                // Close it
                db.db.close();
                // Resolve promise
                deferred.resolve();
            });
        }else{
            deferred.resolve();
        }
        // Get back promise
        return deferred.promise;
    }
    /**
     * Check that the redis connection is open, meaning that the redis-server process is running on the host.
     * @return {Q.Promise<T>|Function}
     */
    public static checkRedisConnection(){
        var config = App._getConfig();
        // Building promise
        var deferred: any = Q.defer();
        if(config.game.checkRedis) {
            // Create the redis client to test to connexion on server
            var redisClient:any = redis.createClient();
            // Get client errors
            redisClient.on("error", function (err) {
                deferred.reject(err);
            });
            // Try applying a key
            redisClient.set("keyTest", true);
            // Now key is applied, try getting it
            redisClient.get("keyTest", function (err, reply) {
                if (err) {
                    deferred.reject("Redis is not running, please make sure to run redis before to start the server. n" + err);
                } else {
                    deferred.resolve();
                }
            });
        }else{
            deferred.resolve();
        }
        // Get back promise
        return deferred.promise;
    }
}

调用类的代码:

Q.fcall(App.checkRedisConnection)
    .then(App.checkMongodbConnection)
    .then(function(result) {
         // run server
    }, console.error);

promises/A+规范明确规定承诺链中的this的值总是未定义的(严格模式)或全局对象:

oncompleted和onRejected必须作为函数调用(即不带this值)。
这里指定的

如果你没有使用像Bluebird这样允许显式设置this(通过.bind)的承诺库,你仍然可以使用TypeScript的胖箭头(也在ES6中)来调用具有词法this的东西。

最新更新