Javascript 添加事件 传入参数 闭包

在用javascript开发html页面的时候, 我们经常遇: 遍历一个某些DOM 结点, 给它添加event, 代码大概如下

var nodeValue = null;
for (var i in domNodes) {
    nodeValue = domNodes[i].val();
    domNodes[i].click(function(){
        //do something, but we need to nodeValue to identify
        console.log(nodeValue);
    });
}

运行下来, 发现所有的click事件, 传入的都是最后一次loop的nodeValue 值.

这是为什么?
nodeValue 作为一个local variable, 一般情况下执行完这段代码, 它的生命周期就应该结束了, 它就在内存不存在了, 可是在这段代码, click事件的这个匿名函数却在内部使用了这个值, 形成了闭包, 所以它的生命周期被延长. 同时这个匿名函数在这里只是被定义, 并不被执行(当触发click事件时候, 才会执行). 这个Loop 在最后一次循环后, 它的值被最后确定为最后一个loop的值, 当有click事件被触发时候, 它的值自然是最后一次赋的值.

如何解决?
那么我们要现在要解决的是: 传入这次循环时候的值, 而不是最后的值. 同时, 这个click 方法接受的是一个 function. 方法如下:
domNodes[i].click(function(curValue){
return function(){
//do something, but we need to curValue to identify
console.log(curValue);
};
}(nodeValue););
首先定义一个匿名函数, 并且声明一个形参, 同时执行这个匿名函数(通过后面加()执行). 那么这个当前值就被传入了. 同时在这个外层匿名函数内部返回一个匿名function, 同时这个内部函数使用了外部函数传入的值, 那么这个外部传入的值的生命周期被延长, 形成闭包, 那么就可以在真正触发click事件的时候使用到了这个值.

Message - RabbitMQ - Clustering

  • RabbitMQ clustering 就是把物理上的多个 RabbitMQ 的 server instance 组成一个逻辑上的 RabbitMQ server instance.
  • Clustering 有效的避免了 hardware failure 导致的系统信息丢失
  • all definitions (of exchanges, bindings, users, etc) are mirrored across the entire cluster.
  • Queues behave differently, by default residing only on a single node, but optionally being mirrored across several or all nodes. Queues remain visible and reachable from all nodes regardless of where they are located.

Message - RabbitMQ - AMQP

  • RabbitMQ 使用AMQP 协议, AMQP 是 Advanced Message Queuing Protocol 的缩写;
  • AMQP 这个网络协议, 称消息中间件为 Broker. Broker 从 producer/publisher 接收消息, 然后 route 到特定的 consumer/Subscriber
  • AMQP 的模型简图
    请输入图片描述
  • AMQP 的 broker 内部的概念有: exchange, route, queue, binding, routeKey, exchange type, ack, confirm.
  • 当一个Message 不能被 route 的时候, Broker 可以返回给 producer, 或者丢弃, 或者扔到一个特殊的队列.
  • AMQP 是一个 programable(可编程) 的协议, 是因为, client 可以定义声明 exchange, queue, binding, 而不是Administer 在 server 上定义. 同时可能出现的问题是: 定义冲突.
  • AMQP 定义了4种 exchange type: direct, fanout, topic, header. Borker route 算法根据 exchange 类型和 binding 有不同.
  • AMQP 的 Connection 是典型的长连接. 一个连接内建立多个 Channel.
  • 一个 AMQP 的 broker 可以 host 多个分开的环境, 每个环境称之为一个 virtual host

Message - RabbitMQ

  • 为什么要有消息系统
    消息系统主要用来处理比较耗时的任务, 如一个 http 请求进来之后,可能需要比较长的处理时间, 可以把这个请求封装为一个 message task, 发到消息系统, 等待后端系统处理, 同时返回 http response 郑州处理中.
  • RabbitMQ 的核心概念
    生产者(producer) -> Exchange -> Queue -> Consumer
  • RabbitMQ 如何保证消息不丢失
    当 Producer 发出之后, 它可以通过 Publisher Confirm 来确认一定发出去了;
    Consumer 有可能没处理完就 crash 了, 不过 queue 可以通过 consumer 的 Ack 来确认消息发到 consumer, 被处理, 并且处理完成;
    RabbitMQ 可以持久化(存入硬盘) Queue & Message 来保证消息不丢失;
  • RabbitMQ 的 exchange type
    direct, topic, headers and fanout
  • RabbitMQ server 端的工具命令是: rabbitmqctl
  • Exchange 和 queue 通过 binding 来确认关系: channel.queueBind("queueName", "exchangeName", "");
  • Producer 发送消息到 Exchange, 并带着 routeKey, Exchange 有 exchange type, queue 和 exchange binding, binding 时候可以设置 routeKey, consumer 通过 queue 接受消息.
  • 一般的队列和发布订阅是通过 exchange 的 exchange type 来实现的. 配合 topic 的 routeKey * and # 两个特殊字符