无法使此关键字在节点模块中工作

时间:2014-10-23 20:55:38

标签: javascript node.js

我正在尝试为节点redis模块构建一个小的包装器库。

var redis  = require('redis'),
    client = redis.createClient();

module.exports = {

    /*
     * Time To Live
     *
     * Time in seconds the cache will remain in
     * memory.
     */
    ttl: 120,

    /*
     * Time To Refresh
     *
     * Time buffer in seconds when the cache should
     * be refreshed. On a cache check, if the ttl
     * is less than the ttr, the cache will be
     * refreshed.
     */
    ttr: 60,

    /*
     * Check Cache
     *
     * Middleware to check if the request is cached
     * before executing the full request.
     */
    check: function (req, res, next) {
        var key = req.url.slice(1, req.url.length).replace('/', ':');
        client.get(key, function (err, value) {
            if (value !== null) {
                res.send(value);
                client.ttl(key, function (err, ttl) {
                    if (ttl < this.ttr) {
                        return next();
                    }
                    return;
                });
            } else {
                return next();
            }
        })
    },

    /*
     * Set Cache
     *
     * Takes a key and a value and stores it in redis.
     * Also takes the full response object "res" and
     * handles sending the response if it has not
     * already been sent.
     */
    set: function (url, value, res) {
        var key = url.slice(1, url.length).replace('/', ':');
        client.set(key, value);
        client.expire(key, this.ttl);
        if (!res.headersSent) {
            res.send(value);
        }
        return;
    },

    /*
     * Keygen Cache
     *
     * Takes a urls substring and creates a keyname
     * in line with redis best practices
    */
    keygen: function (url) {
        var key = url.slice(0,1).replace('/', ':');
        console.log(key);
        return key;
    }

};

我无法弄清楚如何正确使用'this'关键字。如果我尝试引用this.ttl或this.ttr或从module.exports对象中的另一个函数调用this.keygen它总是未定义。我应该使用什么结构来启用同一对象内部的引用函数?

1 个答案:

答案 0 :(得分:2)

您的check函数中嵌套了函数,因此this - 关键字与内部函数上下文有关,而与您的对象无关。

第一个解决方案:

function (req, res, next) {
    var _this = this;
    var key = req.url.slice(1, req.url.length).replace('/', ':');
    client.get(key, function (err, value) {
        if (value !== null) {
            res.send(value);
            client.ttl(key, function (err, ttl) {
                if (ttl < _this.ttr) {
                    return next();
                }
                return;
            });
        } else {
            return next();
        }
    })
}


如果您使用该函数作为回调函数,请将对象绑定到回调函数,如下所示:

// replace "yourModule" with the name of your module
var yourModule = require('./yourModule.js');

// an example for expressjs (use get, post ... or something else)
app.get('/some/url', yourModule.check.bind(yourModule));


<小时/> 第二个解决方案(恕我直言,更好的一个):

另一个解决方案是在您的模块中使用局部变量(这些仅在您的模块中可见 - &gt;这就是您想要的)。
这样更容易:

/*
 * Time To Live
 *
 * Time in seconds the cache will remain in
 * memory.
 */
var ttl = 120;

/*
 * Time To Refresh
 *
 * Time buffer in seconds when the cache should
 * be refreshed. On a cache check, if the ttl
 * is less than the ttr, the cache will be
 * refreshed.
 */
var ttr = 60;

/*
 * Check Cache
 *
 * Middleware to check if the request is cached
 * before executing the full request.
 */
var check = function (req, res, next) {
    var key = req.url.slice(1, req.url.length).replace('/', ':');
    client.get(key, function (err, value) {
        if (value !== null) {
            res.send(value);
            client.ttl(key, function (err, ttl) {
                if (ttl < ttr) {
                    return next();
                }
                return;
            });
        } else {
            return next();
        }
    })
};

/*
 * Set Cache
 *
 * Takes a key and a value and stores it in redis.
 * Also takes the full response object "res" and
 * handles sending the response if it has not
 * already been sent.
 */
var set = function (url, value, res) {
    var key = url.slice(1, url.length).replace('/', ':');
    client.set(key, value);
    client.expire(key, ttl);
    if (!res.headersSent) {
        res.send(value);
    }
    return;
};

/*
 * Keygen Cache
 *
 * Takes a urls substring and creates a keyname
 * in line with redis best practices
*/
var keygen = function (url) {
    var key = url.slice(0,1).replace('/', ':');
    console.log(key);
    return key;
};

/**
 * PUBLIC API
 */
module.exports = {
     check: check,
     set: set,
     keygen: keygen
};


现在,因为您不依赖于模块的上下文,您可以简单地执行此操作:

// replace "yourModule" with the name of your module
var yourModule = require('./yourModule.js');

// an example for expressjs (use get, post ... or something else)
app.get('/some/url', yourModule.check);