【问题标题】:Do I need closure for every single methods that has a wait-for-result callback?我是否需要为每个具有等待结果回调的方法关闭?
【发布时间】:2016-06-01 20:10:33
【问题描述】:

我正在使用 socket.io 和 MySQL 数据库的 nodejs 服务器上工作,当我意识到当从数据库中检索数据很慢时,数据可能随时发生变化。 例如,在每个套接字连接上,我想在用户发出 X 数据时查询数据库以获取用户的信息。

io.on('connection', function(socket) {
    console.log('User connected');
    socket.on('fetchTable', function(data) {
        var number = data.number;
        database.getTable(number, function(error, result) {
            // We'll take it that result is constant for both: 1
            socket.emit('fetchTableResult', result + number);
        });
    });
});

如果 2 个用户同时连接(用户 1 的号码:1,用户 2 的号码:2),用户 1 请求数据库 BEFORE 用户 2 但数据库返回用户 1 的结果太慢,首先处理用户 2 的数据。返回的数据会不一样吗?两个用户都会得到 '3' 作为 'fetchTableResult' 数据,对吗?并且套接字现在不会同时是用户 2 的套接字吗?

解决方案?

io.on('connection', function(socket) {
    console.log('User connected');
    socket.on('fetchTable', function(data) {
        var number = data.number;
        (function(socket, number) {
            database.getTable(number, function(error, result) {
                // We'll take it that result is constant for both: 1
                socket.emit('fetchTableResult', result + number);
            });
        })(socket, number)
    });
});

如果是这样,如果在 database.getTable 内部,我有另一种方法,例如获取网站的 HTML 内容,这需要一些时间,我是否真的需要在内部进行另一个闭包?

例如:

io.on('connection', function(socket) {
    console.log('User connected');
    socket.on('fetchTable', function(data) {
        var number = data.number;
        (function(socket, number) {
            database.getTable(number, function(error, result) {
                // We'll take it that result is constant for both: 1
                (function(socket, result) {
                    // fetch website html data
                    socket.emit('fetchTableResult', result + number);
                })(socket, result)
            });
        })(socket, number)
    });
});

参考:https://github.com/loverajoel/jstips/blob/gh-pages/_posts/en/2016-02-03-implementing-asynchronous-loops.md

【问题讨论】:

  • 第二个代码块中不需要闭包
  • @JaromandaX 你介意解释一下原因吗?是不是因为我已经在我当前的范围内,没有其他东西可以改变socketresult 的值?
  • 听起来你知道为什么

标签: javascript node.js closures


【解决方案1】:

我认为您的第一个示例应该可以正常工作。例如:

document.addEventListener("click", function(event) {
  var x = event.x;
  setTimeout(function() {
    console.log(x);
  }, 1000);
});

尝试在短时间内点击两个不同的位置。正如预期的那样,您会得到不同的结果。


当你在循环中执行异步函数时,你需要一个闭包(实际上是一个 IIFE),例如,这不会按预期工作:

for (var i = 0; i < 2; i++) {
  setTimeout(function() {
    console.log(i);
  }, 1000*i);
}

你必须像这样包装它 IIFE:

for (var i = 0; i < 2; i++) {
  (function(i) {
    setTimeout(function() {
      console.log(i);
    }, 1000*i);
  }(i));
}

或将i 绑定到回调,如下所示:

for (var i = 0; i < 2; i++) {
  setTimeout(function(i) {
    console.log(i);
  }.bind(null, i), 1000*i);
}

我个人更喜欢第二种方法。

但是,当您多次调用异步函数时,您不需要 IIFE,因为该函数本身就是一个闭包。例如:

function test(i) {
  setTimeout(function() {
    console.log(i);
  }, 1000*i);
}

test(0);
test(1);

每次调用test() 时,都会创建另一个作用域,因此i 变量不会被覆盖,它会按预期工作。

【讨论】:

    猜你喜欢
    • 2015-06-13
    • 2016-12-31
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2013-12-15
    • 1970-01-01
    • 1970-01-01
    • 2022-01-05
    相关资源
    最近更新 更多