Nodejs的运行原理-函数回调篇
前言
当客户端向http server 发起TCP链接时,server端会发起一系列的callback调用,这是一个逆向调用的过程;开始于libuv,终止于js代码里的callback(promise then)函数。
如下图所示,http server 正向调用过程,实际大部分的时间花在net.js上,直到最下面的红框,才调用了关键函数createTCP()
function createTCP() {
//绑定tcp_wrap模块,调用tcp constructor。
var TCP = process.binding('tcp_wrap').TCP;
return new TCP();
}
tcp_wrap模块
我们看一下tcpwrap::initialize()的代码:
void TCPWrap::Initialize(Handle<Object> target, Handle<Value> unused, Handle<Context> context) {
Environment* env = Environment::GetCurrent(context); Local<FunctionTemplate> t = FunctionTemplate::New(env->isolate(), New);
t->SetClassName(FIXED_ONE_BYTE_STRING(env->isolate(), "TCP"));
t->InstanceTemplate()->SetInternalFieldCount(1);
// Init properties
t->InstanceTemplate()->Set(String::NewFromUtf8(env->isolate(), "reading"),Boolean::New(env->isolate(), false));
t->InstanceTemplate()->Set(String::NewFromUtf8(env->isolate(), "owner"),Null(env->isolate()));
t->InstanceTemplate()->Set(String::NewFromUtf8(env->isolate(), "onread"),Null(env->isolate()));
t->InstanceTemplate()->Set(String::NewFromUtf8(env->isolate(),"onconnection"),Null(env->isolate())); NODE_SET_PROTOTYPE_METHOD(t, "open", Open);
NODE_SET_PROTOTYPE_METHOD(t, "bind", Bind);
NODE_SET_PROTOTYPE_METHOD(t, "listen", Listen);
NODE_SET_PROTOTYPE_METHOD(t, "getsockname", GetSockName); target->Set(FIXED_ONE_BYTE_STRING(env->isolate(), "TCP"), t->GetFunction());
} NODE_MODULE_CONTEXT_AWARE_BUILTIN(tcp_wrap, node::TCPWrap::Initialize)
利用v8 engine的 functionTemplate 创建一个js类。
类的constructor 是 TCP(),
类的prototype是NODE_SET_PROTOTYPE_METHOD(),
类的属性是t->InstanceTemplate()->Set().
在执行函数createTCP()调用process.binding('tcp_wrap')时,其实会调用到下图。在红框内,可以看到参数target被设置成了export对象,也就是说,tcp_wrap模块真正导出的是TCP函数。
Server.prototype._listen2
结合上图,我们可以看到函数_listen2中调用createServerHandle() 返回了一个_handle对象,并且self._handle.onconnection = onconnection,这一步也非常重要。
AsyncWrap准备工作
AsyncWrap 和Env的代码截图:
准备工作及流程:
callBack的逆向调用
前面都是铺垫,这里才是正题。
正向调用过程,从createServer()开始,到listen()结束,为了创建一个基于TCP的http server。了解socket流程的都知道,到此为止,创建工作实际已经完成,剩下的就是等待客户connect。
而所有的callback执行的目的是对应用程序构造出一个socket的对象,并且基于此对象完成面向连接的数据流读取操作。
下图为调用流程:
First callback
TCP::Listen()通过libuv提供的uv_listen()实现了listen异步调用,并且指定了callback回调函数TCPWrap::OnConnection()。
OnConnection()由libuv的event loop调用。
在看Nodejs Env.h 和 Env-inl.h 中可找到PER_ISOLATE_STRING_PROPERTIES(v)若干引用,就像上面图所示,env->onconnection_string()会返回symbole onconnection。
MakeCall中,通过object()->Get()获取symbole的对应函数。
Other callback
net.js中的onconnection()会被调用,如下图所示:
两个要点,一是创建了socket对象,二是发出了connection时间。
开发者调用createServer()时,其实是在执行new Server(),而类Server中对connection之间有一个监听者,那就是connectionListener(),也就是第三个callback。
通过前文,我想后面的事情就不在赘述了。
Nodejs的运行原理-函数回调篇的更多相关文章
- Nodejs的运行原理-架构篇
前言 本来是想只做一个Nodejs运行原理-科普篇,但是收到了不少私信,要我多分享一些更进阶,更详细的内容,所以我会在接下来的两个月里继续更新Nodejs运行原理. PS:此系列只做Nodejs的运行 ...
- Nodejs的运行原理-调用篇
前言 之前做过Nodejs的架构篇, 有很多朋友留言给我,说没看懂里面的例子,这里我会重新梳理一下,再以http server为例,来解析Nodejs从前端到libuv的调用过程. 正文 回忆a. N ...
- Nodejs的运行原理-libuv篇
前言 这应该是Nodejs的运行原理的第7篇分享,这篇过后,短时间内不会再分享Nodejs的运行原理,会停更一段时间,PS:不是不更,而是会开挖新的坑,最近有在研究RPG Maker MV,区块链,云 ...
- 【原创】分布式之数据库和缓存双写一致性方案解析(三) 前端面试送命题(二)-callback,promise,generator,async-await JS的进阶技巧 前端面试送命题(一)-JS三座大山 Nodejs的运行原理-科普篇 优化设计提高sql类数据库的性能 简单理解token机制
[原创]分布式之数据库和缓存双写一致性方案解析(三) 正文 博主本来觉得,<分布式之数据库和缓存双写一致性方案解析>,一文已经十分清晰.然而这一两天,有人在微信上私聊我,觉得应该要采用 ...
- Nodejs的运行原理-科普篇
前言 Nodejs目前处境稍显尴尬,很多语言都已经拥有异步非阻塞的能力.阿里的思路是比较合适的,但是必须要注意,绝对不能让node做太多的业务逻辑,他只适合接收生成好的数据,然后或渲染后,或直接发送到 ...
- Nodejs的运行原理-生态篇
前言 这里是重点:Nodejs 是由v8 engine,libuv和内置模块组成,可以将v8 engine和 libuv看成一个库,两者是以源码的方式直接编译执行node中去的. 这是一个广泛的介绍, ...
- Nodejs的运行原理-模块篇
前言 使用Nodejs,就不可避免地引用第三方模块,它们有些是Nodejs自带的(例:http,net...),有些是发布在npm上的(例:mssql,elasticsearch...) 本篇章聚焦3 ...
- Pytorch源码与运行原理浅析--网络篇(一)
前言 申请的专栏开通了,刚好最近闲下来了,就打算开这个坑了hhhhh 第一篇就先讲一讲pytorch的运行机制好了... 记得当时刚刚接触的时候一直搞不明白,为什么自己只是定义了几个网络,就可以完整的 ...
- SpringBoot-02 运行原理初探
SpringBoot-02 运行原理初探 本篇文章根据b站狂神编写 pom.xml 2.1.父依赖 其中它主要是依赖一个父项目,主要是管理项目的资源过滤及插件! <parent> < ...
随机推荐
- LuceneNet 实现快速大文件大数据查询
做过站内搜索的朋友应该对Lucene.Net不陌生,因为用普通的sql like查询肯定是不行的,太慢了. 首先说明的是--Lucene.Net只是一个全文检索开发包,不是一个成型的搜索引擎, 它的 ...
- JXLS 2.4.0系列教程(四)——多sheet是怎么做到的
注:本文代码在第一篇文章基础上修改而成,请务必先阅读第一篇文章. http://www.cnblogs.com/foxlee1024/p/7616987.html 本文也不会过多的讲解模板中遍历表达式 ...
- node学习笔记1——require参数查找策略
require参数类型 http.fs.path等,原生模块 ./mod或../mod,相对路径的文件模块 /pathtomodule/mod,绝对路径的文件模块 mod,非原生模块的文件模块 mo ...
- UIScrollerview的contentsize设置
最近被同行的一个朋友问到一个问题"UIScrollerview上添加子控件,给子控件约束好布局之后,还需要给scrollerview重新设置contentsize吗?"于是想到了我 ...
- 阿里云部署SSL证书详解
http://mp.weixin.qq.com/s/NV7Zad4DVEgzG2GCHYJVLw 查找中间证书 为了确保兼容到所有浏览器,我们必须在阿里云上部署中间证书,如果不部署证书,虽然安装过程可 ...
- parse_url 解析 URL,返回其组成部分
parse_url - 解析 URL,返回其组成部分 array parse_url ( string $url [, int $component = -1 ] ) 本函数解析一个 URL 并返回一 ...
- CSS学习笔记day1
1.css的简介 css:层叠样式表 (层叠:一层一层的:样式表:很多的属性和属性值) 使页面显示效果更好 将页面内容和显示样式进行分离,提高了显示功能. 2.css和html的结合方式(4种) 在 ...
- 邓_mysql_面试
问题1:你如何确定 MySQL 是否处于运行状态? 答案: Debian 上运行命令service mysql status,在RedHat 上运行命令service mysqld status.然后 ...
- Struts2中Action接收参数的方法主要有以下三种:
Struts2中Action接收参数的方法主要有以下三种: 1.使用Action的属性接收参数(最原始的方式): a.定义:在Action类中定义属性,创建get和set方法: b.接 ...
- ASP.NET Core 一步步搭建个人网站(6)_单页模式和优化
前言 HI,有段时间没有更新了,主要因为第一年前事情比较多,有些事得忙着张罗下:第二呢,对个人网站进行了一次大范围的优化,主要是申请的云服务器资源有限,1m的网络带宽,带上图片展示的话,打开网站的平均 ...