0

我有这样的代码:

for (var index = 1; index < args.length; index++) {
    var shell = args[index];
    listener.of('/' + shell.namespace || 'shotgun')
        .on('connection', function (socket) {
            socket.on('execute', function (cmdStr, context, options) {
                console.log('Received: ' + cmdStr);
                var result = shell.execute(cmdStr, context, options);
                socket.emit('result', result);
            });
        });
}

我正在使用socket.io,并且正在创建多个命名空间。socket.io 命名空间运行良好,但在execute回调中,对的引用shell始终是 for 循环中创建的最后一个对象。我需要循环的每次迭代来保持shell对该迭代的引用。

4

3 回答 3

3

好吧,最终的答案将是使用let(ECMAScript 6 或node --harmony):

for (let index = 1; index < args.length; index++) {
    let shell = args[index];
    // ...
}

同时,您可以使用闭包或附加function范围来为每次迭代保留不同的index和:shell

function iterator(shell, index) {
    listener.of('/' + shell.namespace || 'shotgun')
        // ...
}

for (var index = 1; index < args.length; index++) {
    iterator(args[index], index);
}

而且,如果argsArray,这也可以用 来完成.forEach()

args.forEach(function (shell, index) {
    listener.of('/' + shell.namespace || 'shotgun')
        // ...
});
于 2013-07-18T17:31:53.090 回答
2

这是使用.bind.

for (var index = 1; index < args.length; index++) {
  var shell = args[index];
  listener.of('/' + shell.namespace || 'shotgun')
    .on('connection', function(socket) {
      shell = this.shell;
      socket.on('execute', function (cmdStr, context, options) {
        console.log('Received: ' + cmdStr);
        var result = shell.execute(cmdStr, context, options);
        socket.emit('result', result);
      });
    }.bind({ shell: shell }));
}
于 2013-07-18T17:32:01.633 回答
2

问题是您正在创建一个引用变量的闭包,shell并在调用函数时评估变量,而不是在定义函数时。您需要创建一个引用循环变量当前值的闭包。有几种方法,但一种是使用IIFE

for (var index = 1; index < args.length; index++) {
    var shell = args[index];
    listener.of('/' + shell.namespace || 'shotgun')
        .on('connection', (function (_shell) { return function (socket) {
            socket.on('execute', function (cmdStr, context, options) {
                console.log('Received: ' + cmdStr);
                var result = _shell.execute(cmdStr, context, options);
                socket.emit('result', result);
            }; }(shell)));
        });
}

注意:您可以shell为 IIFE 的形式参数使用相同的名称 ( ),这会将变量隐藏在外部范围中,但我将其重命名_shell以澄清发生了什么。

于 2013-07-18T17:32:04.687 回答