0

我已经编译了代码(发布在下面):

var keys = [];
var key1="17"; //ctrl
var key2="16"; //shift
var key3="83"; //s

window.addGlobalHotkey = function(callback,keyValues){
    if(typeof keyValues === "number")
        keyValues = [keyValues];

    var fnc = function(cb,val){
        return function(e){
            keys[e.keyCode] = true;
            executeHotkeyTest(cb,val);
        };        
    }(callback,keyValues);
    window.addEventListener('keydown',fnc);
    return fnc;
};

window.executeHotkeyTest = function(callback,keyValues){
    var allKeysValid = true;

    for(var i = 0; i < keyValues.length; ++i)
        allKeysValid = allKeysValid && keys[keyValues[i]];

    if(allKeysValid)
        callback();
};

window.addEventListener('keyup',function(e){
    keys[e.keyCode] = false;
});

addGlobalHotkey(function(){
    var x = getIn("What Task?");
        switch(x)
        {
            case "a":
                //...
            break;
            case "t":
                //...
                break;
            default:
                //...;
        }
},[key1,key2,key3]);

function getIn(text){

    var x = prompt(text);

    if (x != null && x != ''){
        return x;
    }              
}
  • 允许创建热键(在我的情况下为Ctrl+ Shift+ S
  • 旨在调出输入框(又名prompt
  • 并接受一个命令(一些预定义的switch或选项)
  • 节中定义addGlobalHotkey(function(){/PLAY HERE/},[key1,key2,key3]);

所以现在你有了整个背景。它在使用 GreaseMonkey 和 TamperMonkey 的 Firefox、Chrome 中运行良好,并且完全符合我的需要。

但是,我注意到在任何给定选项卡上执行它后,该特定选项卡开始逐渐变慢,挂起,延迟绘制,唯一的解决方案是关闭它。其他选项卡不受影响,仅影响您在执行时所在的选项卡。所以我担心可能存在内存泄漏,这是我缺少的代码中的东西吗?可以以某种方式改进以确保不是这种情况吗?

另外,我注意到虽然 99+% 的时间,它释放键就好了,有时当你按下键盘上的 ANY 键并执行命令时,这表明钩子在之后没有正确清理本身,导致任何键被困并处理触发器,即使不是指定的键,我错过了什么?稳定性能提高吗?

4

1 回答 1

2

您可以做几件事,但我认为没有内存泄漏的原因。

我已经评论了我的编辑。

var keys = [];

// Integers takes less space than strings, and we might as well put it in an array already
var shortcut = [
    17, // ctrl
    16, // shift
    83  // s
];

window.addGlobalHotkey = function(callback, keyValues){
    if(typeof keyValues === "number")
        keyValues = [keyValues];

    // Unfortunately, because you need the cb argument we can't define it outside the addGlobalHotkey method.
    var fnc = function(cb, val){
        return function(e){
            keys[e.keyCode] = true;
            executeHotkeyTest(cb, val);
        };        
    }(callback, keyValues);

    window.addEventListener('keydown', fnc);
    return fnc;
};

window.executeHotkeyTest = function(callback, keyValues) {
    var i = keyValues.length;

    while(i--) {
        // If key is not pressed, we might as well abort
        if(!keys[keyValues[i]]) return;
    }

    callback();
};

window.addEventListener('keyup',function(e) {
    // Remove key instead of setting it to false
    keys.splice(e.keyCode, 1);
});

addGlobalHotkey(function() {
    var x = getIn("What Task?");

    // If x is empty there's no point in resuming
    if(!x) return;

    // If-statements are faster than switches, just saying.
    switch(x)
    {
        case "a":
            //...
        break;
        case "t":
            //...
            break;
        default:
            //...;
    }
}, shortcut);

function getIn(text){
    var x = prompt(text);

    // Altered if statement
    if(typeof x === 'string' && x.length > 0) return x;
}

最潜在的泄漏是数组键只会随着您按下更多不同的键而增长。因此.splice()方法。


编辑

我再次查看了您的代码。我不禁注意到,onkeydown每当您注册一个新的热键时,您都会创建一个新的侦听器。我已经改变了。请尝试以下代码,看看它是否仍然运行缓慢。

/* VARIABLES */

var keysPressed = [];
var hotkeys = [];

/* EVENT LISTENERS */

// Listen for keydown once instead for every hotkey
window.addEventListener('keydown', function(e) {
    // A button was pressed
    keysPressed[e.keyCode] = true;
    checkHotkeys();
}, false);

window.addEventListener('keyup', function(e) {
    // Remove key
    keysPressed.splice(e.keyCode, 1);
}, false);

/* FUNCTIONS */

function checkHotkeys() {
    var i = hotkeys.length;

    while(i--) {
        executeHotkeyTest(
            hotkeys[i].callback,
            hotkeys[i].keys
        );
    }
};

function addGlobalHotkey(callback, keys) {
    if(typeof keys === "number")
        keys = [keys];

    hotkeys.push({
        callback: callback,
        keys: keys
    });
};

function executeHotkeyTest(callback, keys) {
    var i = keys.length;

    while(i--) {
        // If key is not pressed, we might as well abort
        if(!keysPressed[keys[i]]) return;
    }

    callback();
};

function getIn(text){
    var x = prompt(text);

    // Altered if statement
    if(typeof x === 'string' && x.length > 0) return x;
}

/* OTHER */

// Integers takes less space than strings
var shortcut = [
    17, // ctrl
    16, // shift
    83  // s
];

addGlobalHotkey(function() {
    var x = getIn("What Task?");

    // If-statements are faster than switches, just saying.
    switch(x)
    {
        case "a":
            //...
        break;
        case "t":
            //...
            break;
        default:
            //...;
    }
}, shortcut);

编辑#2

我找到了问题!

所以我们一直使用键码作为数组的索引——一个数字索引。这些不是关联的。看看下面的例子。

0: 'abc',
1: 'def',
2: 'ghi'

删除 1

0: 'abc',
1: 'ghi'

删除 2

0: 'abc',
1: 'ghi'

通过将它们转换为字符串,您的数组将成为关联数组,并且正确的键将被删除。

// Listen for keydown once instead for every hotkey
window.addEventListener('keydown', function(e) {
    // A button was pressed
    keysPressed[e.keyCode.toString()] = true;
    checkHotkeys();
}, false);

window.addEventListener('keyup', function(e) {
    // Remove key
    delete keysPressed[e.keyCode.toString()];
}, false);

查看工作演示:http: //jsfiddle.net/rQePB/1/

于 2013-09-12T08:29:21.083 回答