setInterval与settimeout模拟的区别


首先先说明下,node里面的事件循环和浏览器中的是不一致的。

这边浏览器用的是chrome 64

问题1:setInterval(fn,ms)过程,是先把fn放入timer堆,还是先执行?

问题2:setInterval 和 settimeout模拟定时 的使用场景都有哪些?

A1

看了一篇文章,里面讲到node中timers阶段的源码为

void uv__run_timers(uv_loop_t* loop) {
  struct heap_node* heap_node;
  uv_timer_t* handle;

  for (;;) {
    heap_node = heap_min((struct heap*) &loop->timer_heap);//取出timer堆上超时时间最小的元素
    if (heap_node == NULL)
      break;
    //根据上面的元素,计算出handle的地址,head_node结构体和container_of的结合非常巧妙,值得学习
    handle = container_of(heap_node, uv_timer_t, heap_node);
    if (handle->timeout > loop->time)//如果最小的超时时间比循环运行的时间还要小,则表示没有到期的callback需要执行,此时退出timer阶段
      break;

    uv_timer_stop(handle);//将这个handle移除
    uv_timer_again(handle);//如果handle是repeat类型的,重新插入堆里
    handle->timer_cb(handle);//执行handle上的callback
  }
}

里面说到对于repeat类型的handle(setInterval设置的),是先重新插入再执行callback

( 我这边测试发现chrome 64是这样的,node相反。可能node修改过实现?

测试代码

var speed = 1000
var start = Date.now()
var icounter = 0
var tcounter = 0
//t:ms
function sleep(t) {
    let d = Date.now()
    while (Date.now() - d < t) { }
}
setInterval(function () {
    var time = (Date.now() - start) / 1000
    var avg = ++icounter / time
    console.log('<td>setInterval</td><td>' + icounter + '</td><td>' + time.toFixed(3) + '</td><td>' + avg.toFixed(6) + '</td>')
    sleep(50)
}, speed)

浏览器运行效果:

setInterval=>次数:1   所用时间:1.002
setInterval=>次数:2   所用时间:2.001
setInterval=>次数:3   所用时间:3.000
setInterval=>次数:4   所用时间:4.002
setInterval=>次数:5   所用时间:5.002

node运行效果:

setInterval=>次数:1   所用时间:1.003
setInterval=>次数:2   所用时间:2.060
setInterval=>次数:3   所用时间:3.114
setInterval=>次数:4   所用时间:4.164
setInterval=>次数:5   所用时间:5.215

结果分析:

  1. 浏览器先把fn放入timer堆,再执行

  2. node先执行,再把fn放入timer堆


趣味js-只用1和特殊字符生成字符串


180306更新:发现有个http://www.jsfuck.com/ ,上面就做了我想做的东西。也找到了C的生成方法

同时,由于+[]=0,+!+[]=1。我们可以把1也给省略


前言

今天逛justjavac 老哥的博客看到了类似下面的代码

(+([]+(11^(1<<1))+((1+1)<<(1+1))+(11>>>1)+(1^1)+((11>>1)+(1<<1))+(-~1)+(-~1+1)+(1^1)+(1^1)))[(!!1+[])[1^1]+([]+{}+[])[1]+(([]+{})[([]+{})[11-1>>1]+[[],[]+{}+[]][[]+1][1]+(/^/[1]+[])[1|1>>1|1]+[{},11^1,!{}+[]][1+1][1<<1^1]+(11/!{}+{})[~1+(11^1)+~1]+[!!{}+{}][[]&111][1&1]+(/^/[111]+[])[11^11]+[{},[{}]+{},1][1+[]][11-~1+11>>1]+(!!1+{})[1&1>>1]+([]+{1:1}+[])[1|1]+[[]+!!1][111>>>111][1<<1>>1]]+[])[([]+![111])[1|1<<1|1]+[/=/,[]+[][11]][1|[]][1>>1]+([{}]+{})[1+!![1]]+[1,!1+/~/][1%11][1^1<<1]+(!!1+[])[1^1]+[!!/-/+/-/][11%11][+!!1]](11^1<<1,-~11>>1)](~1-~(11^1)<<1<<1)

输出:gahing

实现的原理是什么?

原理

了解 js 隐式类型转换(不懂可以参考这里)的都知道

我们可以通过执行!1+[]得到"false"

具体原理是 false+object 操作会先去调用object的valueOf()方法 发现其值=this

继续调用toString()方法得到"", 结果即false+"" = "false"(又去做了隐式转换)

故我们通过数组下标就可以拿到想要的字符f,a,l,s,e

类似的方法我们还能够拿到

!1+[] = "false"
!!1+[] = "true"
1/[]+[] = "Infinity"
[]/[]+[] = "NaN"
[]+{} = "[object Object]"
[]+/^/[1] = "undefined" /* /^/是正则 */
[]+/\:@$/ = "/\:@$/" /*键盘可见特殊字符放/\ /其中(\用于转义)获取比如拿:就是[1]*/

//可拿到的小写字母有=abcdef ijln orst uy

然后你会发现,26个字母还是有好多不在上面的,并不能通过每次去上面拿字符然后再做拼接


puppeteer初探-测试webrtc


介绍

puppeteer是什么?

它是一个nodejs的库,支持调用Chrome的API来操纵Web 它的dom操作可以完全在内存中进行模拟而不打开浏览器

功能强大,可用于截图、pdf生成、UI测试、表单提交、数据爬取、性能诊断...

官方接口地址:https://github.com/GoogleChrome/puppeteer/blob/master/docs/api.md

安装

通过npm i puppeteer安装

正常是会报错的。

解法方法1:

1.采用cnpm i puppeteer

解法方法2:

1.使用npm i --save puppeteer --ignore-scripts安装并忽略chromium的下载 2.自行下载 chromium 或 采用本地chrome (后面会说明这样的好处)


头脑王者辅助工具


起步

最近直播答题火热,群里也经常看到比拼微信小程序《头脑王者》。我比较笨,凭纯答题只到了黑金段位。鉴于本周刚刚点亮了收集抓包的技能,于是想试着通过这个来做一个辅助工具。


基于docker+Keepalived+Haproxy+Mycat的高可用服务架构设计


  在企业的实际开发部署环境中,docker作为一种虚拟化工具,不仅提供了快速测试,部署的环境,还可用于分布式开发,因此被广泛采用。这里验证了一种最小化高可用分布式解决方案以应对实际部署中的问题,最小化服务器宕机带来的危害。      

  设备:4台Centos7服务器,设计如下: