调试

1、node 版本
v7.10.1
2、服务启动
//httpServer.js
const http = require(‘http’);
http.createServer((req, res) => {
res.end(‘ok’);
}).listen(80);

执行:
node –inspect=127.0.0.1:8887 XXX/httpServer.js
输出:
Debugger listening on port 8887.
Warning: This is an experimental feature and could change at any time.
To start debugging, open the following URL in Chrome:
chrome-devtools://devtools/bundled/inspector.html?experiments=true&v8only=true&ws=127.0.0.1:8887/0822ca0e-3fb7-467b-ae99-998ffcd1926d
Debugger attached.
Chrome浏览器输入devtools://devtools/bundled/inspector.html?experiments=true&v8only=true&ws=127.0.0.1:8887/0822ca0e-3fb7-467b-ae99-998ffcd1926d
httpServer添加断点
3、访问http://127.0.0.1/
4、devtools://devtools/bundled/inspector.html?experiments=true&v8only=true&ws=127.0.0.1:8887/0822ca0e-3fb7-467b-ae99-998ffcd1926d能看到websocket请求信息

发表在 NodeJs | 留下评论

performance使用

0c9f29c9ce8c36ad137763278bab67fb
FP:First Paint
FCP:First Contentful Paint
DCL:DocumentContentLoaded Event HTML、CSS、JavaScript解析完成时触发
L:onload Event 页面其他资源如图片、视频等加载完成后触发,一般在DCL后触发
FMP:First Meaningful Paint
分别对应其左侧的虚线
09ed2fb79630af49994c0d694b08b7c8

发表在 浏览器 | 留下评论

nodejs高并发演示

压测脚本: ab -n 100 -c 100 http://127.0.0.1:8000/
http://127.0.0.1:8000/代码如下:
A).同步阻塞

//index.js
const http = require('http');
let result = 0;
http.createServer((req, res) => {
  let start = new Date();
  console.log(`request arrive--${start}`);
  var waitUntil = new Date(new Date().getTime() + 10 * 1000);
  while(waitUntil > new Date()){}
  console.log(`setTimeout--${result}-response end--${new Date()}`);
}).listen(8000);

执行node index.js
结果:
request arrive–Wed Apr 01 2020 11:05:40 GMT+0800 (GMT+08:00)
setTimeout–0-response end–Wed Apr 01 2020 11:05:50 GMT+0800 (GMT+08:00)
request arrive–Wed Apr 01 2020 11:05:50 GMT+0800 (GMT+08:00)
setTimeout–0-response end–Wed Apr 01 2020 11:06:00 GMT+0800 (GMT+08:00)
request arrive–Wed Apr 01 2020 11:06:00 GMT+0800 (GMT+08:00)
setTimeout–0-response end–Wed Apr 01 2020 11:06:10 GMT+0800 (GMT+08:00)
request arrive–Wed Apr 01 2020 11:06:10 GMT+0800 (GMT+08:00)
…..

能看到请求被阻塞了,需要等待

B).改成异步非阻塞

//index.js
const http = require('http');
const request = require('request');
let result = 0;
http.createServer((req, res) => {
  let start = new Date();
  console.log(`request arrive--${start}`);
  request('http://v.qq.com/', { json: true }, (err, ret, body) => {
    if (err) { return console.log(err); }
    console.log(`setTimeout--${result}-response end--${new Date()}`);
    res.end(`${result} end--${new Date()}`);
  });
}).listen(8000);

执行node index.js
结果如下:
request arrive–Wed Apr 01 2020 11:08:48 GMT+0800 (GMT+08:00)
request arrive–Wed Apr 01 2020 11:08:48 GMT+0800 (GMT+08:00)
request arrive–Wed Apr 01 2020 11:08:48 GMT+0800 (GMT+08:00)
request arrive–Wed Apr 01 2020 11:08:48 GMT+0800 (GMT+08:00)
request arrive–Wed Apr 01 2020 11:08:48 GMT+0800 (GMT+08:00)
request arrive–Wed Apr 01 2020 11:08:48 GMT+0800 (GMT+08:00)
request arrive–Wed Apr 01 2020 11:08:48 GMT+0800 (GMT+08:00)
request arrive–Wed Apr 01 2020 11:08:48 GMT+0800 (GMT+08:00)
request arrive–Wed Apr 01 2020 11:08:48 GMT+0800 (GMT+08:00)
request arrive–Wed Apr 01 2020 11:08:48 GMT+0800 (GMT+08:00)
request arrive–Wed Apr 01 2020 11:08:48 GMT+0800 (GMT+08:00)
……
Error: getaddrinfo ENOTFOUND v.qq.com
at GetAddrInfoReqWrap.onlookup [as oncomplete] (dns.js:60:26) {
errno: ‘ENOTFOUND’,
code: ‘ENOTFOUND’,
syscall: ‘getaddrinfo’,
hostname: ‘v.qq.com’
}
setTimeout–0-response end–Wed Apr 01 2020 11:09:16 GMT+0800 (GMT+08:00)
setTimeout–0-response end–Wed Apr 01 2020 11:09:17 GMT+0800 (GMT+08:00)
setTimeout–0-response end–Wed Apr 01 2020 11:09:18 GMT+0800 (GMT+08:00)
setTimeout–0-response end–Wed Apr 01 2020 11:09:18 GMT+0800 (GMT+08:00)
setTimeout–0-response end–Wed Apr 01 2020 11:09:18 GMT+0800 (GMT+08:00)
setTimeout–0-response end–Wed Apr 01 2020 11:09:18 GMT+0800 (GMT+08:00)
setTimeout–0-response end–Wed Apr 01 2020 11:09:19 GMT+0800 (GMT+08:00)
….
可以看到高并发的效果,每个请求都被处理了

发表在 NodeJs | 留下评论

es6模块

本文介绍浏览器环境的es6模块
浏览器环境中,type=”module”自动标志这个内联或者外联脚本是一个模块。一般模块脚本建议后缀为.mjs,这也与nodejs的保持一致,nodejs中es6的模块化特性只支持.mjs后缀的文件(nodejs9+ :node –experimental-modules 1.mjs).
es6的模块特性:
1.天然自带异步特性,即自带defer,es6模块按顺序先后执行

<script type="module" src="./2.js"></script>
<script type="module">
    console.log('4.type-module.module');
</script>
<script defer>
    console.log('1.defer script');
</script>
<script>
    console.log('2.script');
</script>
<script defer src="./3.js"></script>

输出1.defer script后外链的输出2.script 后 2.js(外链js模块由于顺序靠前,也在非外链js模块前执行,所以能保证顺序)然后4.type-module.module 最后3.js.
内联script没有defer属性,设置defer属性无效,无视defer。
2.支持async,异步加载脚本,区别于defer的保证执行顺序,其谁先加载好谁先执行。
3.同一个js只会加载且执行一次
4.总是CORS跨域请求,所以非同源会报错,需要模块资源服务端配置Access-Control-Allow-Origin
5.模块脚本默认不发送cookie等。需要设置crossorigin=”use-credentials”来携带cookie。API接口会带cookie不用修改
6.天然严格模式
7.静态import和动态import:静态import在首次加载时会把全部资源都加载下来。而动态import按需加载
a).静态import

<script async type="module">
import * as a from './1.js'
</script>

b).动态import(此import非函数,返回promise)

<script>
setTimeout(() => {
    import('./1.js').then(function (a) {
        console.log('1---', a)
    });
}, 5000);
</script>

7.import必须是绝对地址或者相对地址。
Uncaught (in promise) TypeError: Failed to resolve module specifier “3.js”. Relative references must start with either “/”, “./”, or “../”.

参考文章:
万岁,浏览器原生支持ES6 export和import模块啦!

发表在 JavaScript, 浏览器, 规范 | 留下评论

es6与JavaScript关系

javascript是一种语言、HTML也是一种语言,而浏览器有解析JavaScript和HTML的引擎,所以其能运行这两种语言。
那es6又是什么呢?
这就要涉及到历史知识了,先有JavaScript,后来JavaScript的创造公司把JavaScript委托给ECMA大公司,大公司来制定标准,即ECMAScript规范,es规范,各浏览器厂商根据规范来实现,这个实现就是JavaScript。其实都是代号而已,es6是ECMAScript的2015年规范,有的浏览器遵循此规范进行了实现,而有的浏览器比较倔强还未实现或者部分实现了。

浏览器原生支持JavaScript。所以JavaScript能在浏览器运行,但是浏览器对js的兼容性不同,导致有些js代码在某些不兼容浏览器上不能正确使用,比如attachEvent和attachEventLister这两个API就分别对应IE和其他浏览器。

那么es6是如何被应用到浏览器的呢?
刚才说了,不是所有的浏览器都支持es6,网上给了两种实践:
第一种:es6被babel编译成es5用;因为es5基本都被现在浏览器实现了
第二种:script type=module与nomodule分别对应兼容或者不兼容es6时的解决方案
第一种比较好理解,我们看第二种。

<script type="module" src="module.mjs"></script>
<script nomodule src="fallback.js"></script>

对于支持ES6模块导入的浏览器,自然也支持原生的nomodule属性,此时fallback.js是忽略的;但是,对于不支持的老浏览器,无视nomodule、和type=module,此时module.mjs不执行,而fallback.js就会执行,于是浏览器全兼顾。
参考文章:
译」ES5, ES6, ES2016, ES.Next: JavaScript 的版本是怎么回事?
详解JavaScript与ECMAScript的区别
万岁,浏览器原生支持ES6 export和import模块啦!

发表在 JavaScript | 留下评论

捕获和冒泡演示例子

A

B

C


冒泡:c->b->a
捕获:a->b->c

发表在 JavaScript | 留下评论

express框架 使用session 登录

express-session使用session登录,session可以存入内存,或者存入数据库,如存入MongoDB,需要connect-mongo

_.extend(conf, {
    store: new MongoStore({
        url: 'mongodb://127.0.0.1:27017/dbname'
    })
});

express封装了request和response对象。

// session存储
request.session = {
    username: 'xiaoming'
};

request每次携带cookie中的connect.sid,通过这个ID去MongoDB数据库里或者内存里读出session内容。

发表在 NodeJs | 留下评论

nodejs

阻塞是指在 Node.js 程序中,其它 JavaScript 语句的执行,必须等待一个非 JavaScript 操作完成。这是因为当 阻塞 发生时,事件循环无法继续运行 JavaScript。

在 Node.js 中,JavaScript 由于执行 CPU 密集型操作,而不是等待一个非 JavaScript 操作(例如 I/O)而表现不佳,通常不被称为 阻塞。在 Node.js 标准库中使用 libuv 的同步方法是最常用的 阻塞 操作。原生模块中也有 阻塞 方法。

在 Node.js 标准库中的所有 I/O 方法都提供异步版本,非阻塞,并且接受回调函数。某些方法也有对应的 阻塞 版本,名字以 Sync 结尾。

我们说nodejs是高并发的,nodejs并发是什么概念呢?

nodejs 无中间件概念,中间件的概念是框架引入的,比如express。express的中间件更类似于插件plugin的概念。

事件循环和执行JavaScript在一个线程里,JavaScript是单线程的。
nodejs调度有阻塞调度和非阻塞调度。
对javascript阻塞的概念:JavaScript的执行必须等一个非JavaScript的操作执行完成,譬如JavaScript执行必须等读取文件结束才能继续执行就是阻塞操作。
而nodejs被称为非阻塞,是因为其JavaScript执行一般不受非JavaScript操作的阻塞,而是受限于CPU密集型操作。

JavaScript是单线程的,定时器是如何工作的呢?

首先 setTimeout 和 setInterval 都不是ECMAScript规范或者任何JavaScript实现的一部分。它是由浏览器实现,并且在不同的浏览器也会有所差异。定时器也可以由 Nodejs 运行时本身实现.
setTimeout和setInterval的运行机制,是将指定的代码移出本轮事件循环,等到下一轮事件循环,再检查是否到了指定时间。如果到了,就执行对应的代码;如果不到,就继续等待。
参考文章:从零开始再学 JavaScript 定时器

除了setTimeout和setInterval这两个方法,Node.js还提供了另外两个与”任务队列”有关的方法:process.nextTick和setImmediate。它们可以帮助我们加深对”任务队列”的理解。

process.nextTick方法可以在当前”执行栈”的尾部—-下一次Event Loop(主线程读取”任务队列”)之前—-触发回调函数。也就是说,它指定的任务总是发生在所有异步任务之前。setImmediate方法则是在当前”任务队列”的尾部添加事件,也就是说,它指定的任务总是在下一次Event Loop时执行,这与setTimeout(fn, 0)很像

参考文章:JavaScript 运行机制详解:再谈Event Loop

官方认为process.nextTick被滥用了,所以提出了setImmediate
参考文章:event-loop-timers-and-nexttick

Node.js 通过事件循环机制(初始化和回调)的方式运行 JavaScript 代码,并且提供了一个线程池处理诸如文件 I/O 等高成本的任务。Node 可伸缩性的秘诀在于它仅使用了极少数的线程就可以处理大量客户端连接。 在 Node 中,有两种类型的线程:一个事件循环线程(也被称为主循环,主线程,事件线程等)。另外一个是在工作线程池里的 k 个工作线程(也被称为线程池)。
Node 使用事件驱动机制:它有一个事件轮询线程负责任务编排,和一个专门处理繁重任务的工作线程池。
参考文章:dont-block-the-event-loop

发表在 JavaScript, NodeJs | 留下评论

javascript 定时器setTimeout

定时器

const s = new Date().getSeconds();

setTimeout(function() {
  // 输出 "2",表示回调函数并没有在 500 毫秒之后立即执行
  console.log("Ran after " + (new Date().getSeconds() - s) + " seconds");
}, 500);

while(true) {
  if(new Date().getSeconds() - s >= 20) {
    console.log("Good, looped for 2 seconds");
    break;
  }
}

Good, looped for 2 seconds
Ran after 20 seconds
定时器异步操作,必须等主线程执行完才会执行。

参考:
EventLoop

发表在 JavaScript | 留下评论

setTimeout最小延迟时间

var start = new Date().getTime();
function foo () {
    var end = new Date().getTime();
    console.log(&quot;Execution time1-foo: &quot;, (end - start));
}
setTimeout(foo);setTimeout(foo, 0);

输出两次: Execution time1-foo: 1

HTML5规范规定最小延迟时间不能小于4ms,即x如果小于4,会被当做4来处理。 不过不同浏览器的实现不一样,比如,Chrome可以设置1ms,IE11/Edge是4ms。

发表在 JavaScript | 留下评论