读<了不起的Node.js>-04.事件轮询,非阻塞IO,V8

阻塞和非阻塞IO

  • node引入了一个复杂的概念,共享状态的并发
  • 得对回调函数如何修改当前内存中得变量(状态)特别小心
  • 特别注意对错误的处理是否会潜在的在修改这些状态,从而导致整个进程不可用
  • 时刻避免运行时错误的出现

阻塞

  • node里面有事件轮询,意味本质上来说,node会先注册时间,随后不断地询问内核这些时间是否已经分发,当时间分发时,对应的毁掉函数就会被触发,然后继续执行下去,如果没有事件触发,则继续执行其他代码,知道有新事件时,再去执行对应的回调函数
//事件轮询
console.log("hello");

setTimeout(() => {
    console.log('world');
}, 4000);

console.log('bye');

单线程的世界

  • node 是单线程的,在没有第三方模块的版主下是无法改变这一事实的
let start = Date.now();

setTimeout(function () {
    console.log(Date.now() -start);

    for (let i = 0 ; i<100000000;i++){

    }
},1000);

setTimeout(function () {
    console.log(Date.now() - start);
}, 2000);

  • 1001
    2000

  • 当第一个时间分发下去的时候,会执行js毁掉函数,由于回调函数需要执行很长一段时间

  • 所以下一个事件轮询的时间就不一定是2秒

  • node的众多模块都是非阻塞的,执行任务也变成了异步

错误处理

  • node应用依托扎起一个拥有大量共享状态的大进程中
  • 例子
let http = require('http');
http.creatServer(function(){
    thow new Error("错误不会被捕捉")
}).listen(3000)
  • 这个代码是跑不动的 因为报错没有被捕获 进程会崩溃
  • 避免上面的问题
  • 我们需要添加一个uncatchException处理器,这个时候进程不会退出,并且之后的事情都是可空的
  • 例子
let http = require('http');


process.on('uncaughtException', function (err) {
    console.log(err);
    process.exit(1);
});


http.createServer(function () {
    throw new Error("错误跳出来了");
}).listen(8080);

  • 除了uncaughtException 和error时间外,绝大部分node异步api接受的回调函数,第一个就是错误对象或者是null
let fs = require('fs');

fs.readFile('', function (err, data) {
    if (err) return console.error(err);
    console.log(data);
});
  • 错误的处理每一步都很重要,它能让你更加安全

堆栈追踪

  • 在js中,当错误发生的时候,在错误信息中可以看到一系列的函数调用,这称为堆栈追踪
  • 例子
function c() {
    b();

}

function b (){
    a();
}

function a() {
    throw new Error("错误出来额")
}

c();

/*
* E:\TheGreatNodeJs\day01\12.堆栈追踪.js:11
    throw new Error("错误出来额")
    ^

Error: 错误出来额
    at a (E:\TheGreatNodeJs\day01\12.堆栈追踪.js:11:11)
    at b (E:\TheGreatNodeJs\day01\12.堆栈追踪.js:7:5)
    at c (E:\TheGreatNodeJs\day01\12.堆栈追踪.js:2:5)
    at Object.<anonymous> (E:\TheGreatNodeJs\day01\12.堆栈追踪.js:14:1)
    at Module._compile (module.js:652:30)
    at Object.Module._extensions..js (module.js:663:10)
    at Module.load (module.js:565:32)
    at tryModuleLoad (module.js:505:12)
    at Function.Module._load (module.js:497:3)
    at Function.Module.runMain (module.js:693:10)
*/
  • 从上可以看到导致错误发生的函数调用路径,下面我们来引入事件轮询查看一下
function c() {
    b();

}

function b (){
    a();
}

function a() {
    setTimeout(function () {

        throw new Error("错误出来额")
    },10)
}

c();

/*
* E:\TheGreatNodeJs\day01\13.堆栈追踪(事件轮询.js:13
        throw new Error("错误出来额")
        ^

Error: 错误出来额
    at Timeout._onTimeout (E:\TheGreatNodeJs\day01\13.堆栈追踪(事件轮询.js:13:15)
    at ontimeout (timers.js:498:11)
    at tryOnTimeout (timers.js:323:5)
    at Timer.listOnTimeout (timers.js:290:5)
* */
  • 这里面try catch是不可行的,这会直接抛出未捕获异常,并且catch永远都不会执行
©著作权归作者所有,转载或内容合作请联系作者
【社区内容提示】社区部分内容疑似由AI辅助生成,浏览时请结合常识与多方信息审慎甄别。
平台声明:文章内容(如有图片或视频亦包括在内)由作者上传并发布,文章内容仅代表作者本人观点,简书系信息发布平台,仅提供信息存储服务。

相关阅读更多精彩内容

友情链接更多精彩内容