第一坑:作用域
首先,有一个关于this的面试题,是这样的:
var fullname = 'John Doe';
var obj = {
fullname: 'Colin Ihrig',
prop: {
fullname: 'Aurelio De Rosa',
getFullname: function() {
return this.fullname;
}
}
};
console.log(obj.prop.getFullname());
var test = obj.prop.getFullname;
console.log(test());
主要考察的是this的指向,很明显,this是根据上下文的执行环境决定的,obj.prop.getFullname()
的上下文是obj.prop,而执行var test = obj.prop.getFullname
,实际上是window.test = obj.prop.getFullname;
所以window.test()
的this指向的是window,该题的结果为:先打印出Colin Ihrig,然后再打印出John Doe。但是,但问题还没有结束,变个形:
var fullname = 'John Doe';
var obj = {
fullname: 'Colin Ihrig',
prop: {
fullname: 'Aurelio De Rosa',
getFullname: function() {
setTimeout(function () {
console.log(this.fullname);
},100);
return this.fullname;
}
}
};
console.log(obj.prop.getFullname());
var test = obj.prop.getFullname;
console.log(test());
那现在呢,在setTimeout中会弹出什么?当时确实有那么几毫秒难住了我,一想,这个setTimeout,不就相当于window.setTimeout嘛,所以,setTimeout中的this依旧指向window,打印的结果为:Colin Ihrig。
第二坑:执行顺序
还是一个面试题,如下:
setTimeout(function(){ t = false; }, 1000);
while(true){}
alert('end');
问题来了:alert是否能够弹出?为什么?问题的答案是:不能弹出来,因为JS的单线程的,永远的单线程。在while(true)的时候陷入了死循环,就再先出不来了。关于JS的执行机制,请看这里:JavaScript 运行机制详解:再谈Event Loop这篇文章,已经很详细了,我就不多说了。
疑惑:时间点问题
然后,同事问了我个比较诡异的问题,如下:
console.log(1);
setTimeout(function() {
console.log('timeout invoke');
console.timeEnd('timeout');
}, 2000);
console.log(2);
console.time('hard');
console.time('timeout');
for (var i = 0;i<2000000000;i++) {}
console.timeEnd('hard');
console.log(3);
在chrome下,time的标志点hard的大概时间的13秒左右,那么问题来了,setTimeout的第二个参数若为2000(2秒),timeout这个时间为多少?如果为16000(16秒),时间为多少? 经过测试发现,如果这个setTimeout的时间设置为小于13秒,setTimeout会在console.log(3)后立即执行(与hard标志点间隔特别小),如果大于13秒,就在console.log(3)后的t-13秒后触发。 这就让我们很是疑惑,疑惑的点在于在浏览器内部。
- 是什么时候开始进行setTimeout的时间打点呢?
- JS是单线程的,是哪个线程打的点呢?
而经过测试发现,是在执行到setTimeout这句话的时候, 就已经打了点,如果回头执行队列的时间大于setTimeout设置的时间,就再等到了那个时间在触发setTimeout的回调, 如果小于setTimeout设置的时间,就立即执行(实际上已经延时太多了,这就是证明setTimeout不准的铁证,其实就算没有这种影响,也是不准的)。 具体可以参考这篇 JavaScript的单线程性质以及定时器的工作原理
但是第二个问题呢?我是这么想的:JS的单线程的,但是浏览器不是啊,所以是浏览器的另外一个线程负责的打点,如果您有不同的想法,请反馈给我吧,不胜感激。
最后
最近在研究一些原生JS的基础以及深入,发现真是路漫漫其修远兮,为自己加油!
本文链接:setTimeout的若干坑,转载请注明。
第一章. 安装,简介和初探
第二章. exchange,queue,binding介绍 订阅发布 工作队列(消费者集群)
本章收尾 介绍API CommandLine 以及其他功能
源码地址 https://github.com/dubing/MaoyaRabbit
RabbitMQ API
RabbitMQ Server提供了丰富的http api。
举个列子
需要HTTP基本身份验证。默认的用户名/密码为guest/guest。
这些返回值得意义我从官网搬来解释,为了避免翻译的问题导致大家理解的误差这里直接给出原文
cluster_name | The name of the entire cluster, as set with rabbitmqctl set_cluster_name . |
erlang_full_version | A string with extended detail about the Erlang VM and how it was compiled, for the node connected to. |
erlang_version | A string with the Erlang version of the node connected to. As clusters should all run the same version this can be taken as representing the cluster. |
exchange_types | A list of all exchange types available. |
listeners | All (non-HTTP) network listeners for all nodes in the cluster. (See contexts in /api/nodes for HTTP). |
management_version | Version of the management plugin in use. |
message_stats | A message_stats object for everything the user can see - for all vhosts regardless of permissions in the case of monitoring and administrator users, and for all vhosts the user has access to for other users. |
node | The name of the cluster node this management plugin instance is running on. |
object_totals | An object containing global counts of all connections, channels, exchanges, queues and consumers, subject to the same visibility rules as for message_stats . |
queue_totals | An object containing sums of the messages , messages_ready and messages_unacknowledged fields for all queues, again subject to the same visibility rules as for message_stats . |
rabbitmq_version | Version of RabbitMQ on the node which processed this request. |
statistics_db_node | Name of the cluster node hosting the management statistics database. |
statistics_level | Whether the node is running fine or coarse statistics. |
又或者通过api查询虚拟主机
许多api的URI需要一个虚拟主机路径的一部分的名字,因为名字只有唯一在一个虚拟主机识别物体。作为默认的虚拟主机称为“/”,这将需要被编码为“%2F”。
在我的demo程序中对应的api功能可以通过这里的功能来实现
其更丰富的功能可以参考官网说明文档 http://hg.rabbitmq.com/rabbitmq-management/raw-file/3646dee55e02/priv/www-api/help.html
以及 http://hg.rabbitmq.com/rabbitmq-management/raw-file/rabbitmq_v3_3_5/priv/www/api/index.html
一般来说我们常用的我在应用程序中已经给出 例如查看所有队列等
RabbitMQ CommandLine
除了丰富的http api,rabbitmq server自然也有其很全面命令行。
例如查询所有exchange。
查询所有队列以及他们包含的消息数目
rabbitmqctl更多的命令说明参考 http://www.rabbitmq.com/man/rabbitmqctl.1.man.html
Message的BasicGet于consume的区别
consume的功能上一张介绍过,basicget更偏向于我们平时用过的其他类型的MessageQueue,它就是最基本的接受消息,consume的消费针对basicget来说属于一个长连接于短连接的区别。
消费者关系一旦确定,基本上默认它就是在侦听通道的消息是否在生产。而basicget则是由客户端手动来控制。
在demo中在下图所示处区分
如果你选择了消费消息,那么基本上代码层面是这样来完成的
channel.BasicQos(0, 1, false);
channel.BasicConsume(queue.name, rbAckTrue.Checked, consumer);
while (true)
{
var e = consumer.Queue.Dequeue();
MessageBox.Show(string.Format("队列{0}获取消息{1},线程id为{2}", queue.name, Encoding.ASCII.GetString(e.Body), Process.GetCurrentProcess().Id));
Thread.Sleep(1000);
}
上一章节介绍了 消费者如何做分布式或者说是集群,很多同学可能对server端的集群也很感兴趣,鉴于单机的应用程序这里就不多介绍了,给出官网的传送门
http://www.rabbitmq.com/clustering.html
本篇收尾 有点狗尾续貂的感觉 旨在按照之前的计划 放出源码 希望对大家有帮助
本文链接:一个winform带你玩转rabbitMQ(三) 附源码,转载请注明。
没有评论:
发表评论