JS怎么调用C++
Node.js不是什么
不是web结构
- Node.js并不是web后端结构
- 所以不能把Node.js与Flask或Spring比较
不是编程言语
- Node.js并不是后端的JS
- 所以不能把Node.js与Python或PHP对比
Node.js是什么
是一个渠道
Node.js组合了许多技能
- V8引擎
- libuv
- C/C++完结的
c-ares(域名解析)、http-parser(解析http)、OpenSSL(做https)、zlib(做加密)
等库
Node.js技能架构
随着Node.js的版别现已从0.8升级到12.11.1,其架构也在一向改变中
假如要看源代码,引荐看0.10版别,github中找到nodejs选择0.10版别即可
github.com/nodejs/node…
由于这一版别运用了好久一段时刻,并且源代码比新版少许多
假如想要了解更多,能够查看 github.com/yjhjstz/dee…
咱们大部分时分,只需求学习Node.js规范库即可
对于其他模块,有一个大约的了解就行
等对Node.js内部完结感兴趣的时分,再去了解规范库之外的东西
不过你可能要写好 C / C++
什么是bindings
布景
- C/C++完结了一个http_parser库,很高效
- 咱们只会写JS,但是又想调用这个库
- 直接调用必定是不能成功的,咱们需求一个中心的桥梁
bindings
- Node.js用C++对http_parser进行封装,使它契合某些要求(如:它的数据类型和JS数据类型做了一一对应的封装),封装的文件叫做http_parser_bindings.cpp(C++的代码)
- 用Node.js供给的编译东西将其编译为.node文件
- JS代码能够直接require这个.node文件
- 这样JS就能调用C++库,中心的桥梁便是binding(http_parser_bindings.cpp)
- 由于Node.js供给了许多binding,所以加个s
- 这便是bindings
JS 与 C++ 交互
查看: nodejs.cn/api/addons.…
插件通常会露出能够从 Node.js 中运转的 JavaScript 拜访的目标和函数。 当从 JavaScript 调用函数时,输入参数和回来值必须映射到 C/C++ 代码和从 C/C++ 代码映射。
在test.js就完结了经过JS引入addon这样的node.js文件,调用了addon.cc(C/C++)中的add方法
C++ 调用JS回调
查看: nodejs.cn/api/addons.…
插件中的常见做法是将 JavaScript 函数传给 C++ 函数并从那里履行它们
args[0]便是JS中的那个函数,但是args[0]不能直接给C++,C++是看不懂JS函数的,Node.js供给了Cast的东西,它能够把JS的函数转化为C++能看懂的函数cb。JS中的函数addon就会被C++调用,调用的时分传了参数hello world(C++中结构了JS能看懂的string) ,于是就输出了hello world
只要能让JS调用C++的代码,JS的才能就会被无限扩大
Node.js供给的binding咱们能够运用,假如现在有一个新的C++库,Node.js没有把它绑定进来怎么办?
Node.js还供给别的一个功用: 答应你自己写C++,把C++库绑定到JS上,JS就能够调用C++库了,这便是Node.js的别的一个才能,C/C++插件(自定义其他才能)
Node.js的依靠
在Node.js V0.10 版别中有7个依靠,咱们主要需求掌握两个依靠v8和uv(也便是libuv)
,其他的优先级往后放
- cares:DNS
- http_parser: http
- npm: 包办理器
- openssl: https
- zlib: 压缩
libuv & v8 的功用
libuv是什么
布景
- FreeBSD 体系上有kqueue
- Linux体系上有epoll
- Windows 体系上有IOCP
- Ryan为了完结一个跨渠道的异步I/O(所有的输入和输出,如:写文件,拜访网络,连接打印机打印文件即体系和外界进行的所有交互)库,开始写libuv
- libuv会依据体系主动选择合适的计划(kqueue/epoll/IOCP)
功用
- 能够用于TCP(http是基于TCP/IP,只要能操作TCP就能够做http服务器)/UDP(QQ谈天)/DNS(baidu.com对应的IP)/文件(文件的读取)等的异步操作
- 有了这些功用Node.js就能够脱节IO瓶颈了,涉及到IO的操作交给C言语去做,JS只负责简单的调用
v8是什么
功用
- 将JS源代码变成本地代码(01)并履行
- 保护调用栈,确保JS函数的履行次序
- 内存办理,为所有目标分配内存
- 废物收回,重复运用无用的内存(废物收回的目的是为了再次重复运用,由于内存是有限的,比方:你用完了2k的内存,用完了就得还给我,还要给下一程序运用呢!)
- 完结JS的规范库(如:数组的sort、数组的splice等函数)
- v8自身是多线程的
留意
- V8不供给DOM API(如:在V8中不能操作
douemnt.createElement()...
,它是浏览器供给的) - V8履行JS是单线程的(V8自身是多线程的)
- 能够敞开两个线程分别履行JS(并不是真实意义上的多线程,这两个线程之间毫无瓜葛)
- V8自身是包括多个线程的,如:废物收回为单独线程
- 自带 eventloop 但 Node.js并没有运用自带的eventloop而是基于libuv自己做了一个eventloop
eventloop
Event Loop 是什么
什么是Event
- 计时器到了就会发生一个工作,这个工作发生就会履行回调(内部的)
- 文件能够读取了、读取出错了的时分是操作体系要单独生成一个工作告知JS。如:复制文件到U盘上,假如发现此刻现已有别的一个文件也在复制,那么此刻第二个复制文件就会很慢,由于硬盘的读写速度是有极限的(外部的,文件再在硬盘上,而硬盘和操作体系是分开的)
- socket有内容了、关闭了。如:用户恳求了咱们的服务器,socket有内容了操作体系得告知JS要开始读用户的内容。socket关闭了,也得告知JS(外部的,socket一般为别的一台机器传过来的)
什么是Loop
- Loop 便是循环,比方: while(true) 循环
- 由于工作是分优先级的,所以处理起来也是分先后的
举例:
三种不同的工作
setTimeout(f1,100) // 计时器届时了
fs.readFile('/1.txt',f2) // 文件能够读了
server.on('close',f3) // 服务器关闭了
假如一起触发,Node会怎么办?履行f1?f2?f3
- 必定会有某种次序(优先级)
- 这种次序应该是人为规则的(假如有读文件就先读文件 => 假如有恳求就先处理恳求=>假如有计时器就履行计时器 ====> 进入循环Loop => 假如有读文件就先读文件 => 假如有恳求就先处理恳求 => .......)
- 所以Node.js需求依照次序轮询每种工作
- 这种轮询往往都是循环的,1->2->3->1->2->3
EventLoop
- 操作体系能够触发工作,JS能够处理工作
- Event Loop 便是对工作处理次序的办理
Event Loop
次序示意图
- 读官方文档是最好的方法
- 或许/post/684490…
重点阶段
- timers 查看计时器
- poll 轮询阶段,处理大部分恳求(如:读文件,http恳求),查看体系工作
- check 查看阶段,处理 setImmediate 回调
- close callbacks 看下有没有sockert关闭的回调
- 再回到timers 查看计时器。。。 如此循环下去
- 假如Node.js发现没有什么事做就会停在poll(轮询)阶段,假如发现有工作做,如履行
setImmediate
就会进入下个阶段check(while循环,一向问操作体系有没有文件能够读、有没有网络恳求能够处理、。。。。)。poll阶段是Node.js停留时刻最长的、优先级最高的 - 其他阶段用的较少
大部分时分timers中的定时器是后履行的(虽然它在最前面),由于定时器至于在大于或等于时刻的时分才会被履行,假如时刻没到就会履行timers下面的阶段,等其他阶段如poll阶段或许check阶段履行完了,计时器的时刻到了或许超了再履行timers
一个面试题
请问下面的代码哪个先履行?
setTimeout(f1,0)
setImmediate(f2)
===》 不确定
(1) 大部分情况下是setImmediate先履行,由于大部分时分,Node.js都是停留在poll 阶段,这个时分假如要履行JS就会先经过check阶段,这个阶段便是处理setImmediate
(2) 有一个情况是破例的: Node.js第一次进来时会先看下有没有timers
留意
- 大部分时刻,Node.js都停留在poll轮询阶段(假如这个阶段比较耗时,那么timers就会主动往后推)
- 大部分工作都在poll阶段被处理,如文件、网络恳求
总结
- 用libuv进行异步I/O操作(如:让libuv读文件,文件读完后Node.js顶替后边的工作(Node.js能够处理文件了!!!)
- 用event loop 办理不同工作处理次序(先polls(操作体系) -> check -> close -> timers -> polls(操作体系) … 如此循环) (Node.js能够办理工作的次序了!!!)
- 用C/C++ 库高效处理DNS/HTTP…(Node.js又能够处理网络了!!!)(由于Node.js是凭借C++处理网络恳求,因而处理网络恳求速度很快)
- 用bindings 让JS能和C/C++沟通(JS也能够调用C++的代码了!!!)(把C++代码编译成
.node
文件给JS去require
,require的进程中JS传个函数给C++,C++调用JS) - 用V8运转用户写的JS(写好了JS代码在哪里运转JS代码呢?)
- 用Node.js规范库进化JS代码(都让用户写JS,用户就不爽了,帮用户写好了一些东西,用户直接用)
- 这便是Node.js
Node.js作业流程
-
Application
便是咱们写的JS - 咱们写JS放到V8上运转
- 运转的进程中发现JS中写了一个定时器
- Node.js调用Node.js的bindings / API ,把定时器放到 Event Loop 中,告知Event Loop 100毫秒之后要履行一个函数
- Event Loop 中有许多不同的队列(如:timers、poll、check等),Event Loop 会等待恰当的时机去履行队列中的代码
- 假如此刻在poll阶段需求读一个文件,这时Event Loop 就会运用libuv开一个线程去读这个文件(JS不参与),读完文件之后,操作体系就会回来一个工作给Event Loop,Event Loop 发现文件读好了,就传回给V8,然后就传回到咱们写代码的当地
- 处理网络恳求也一样libuv得到了用户传过来的网络恳求,就会把它放到 Event Loop 中的poll阶段,poll阶段得到这个恳求之后,就会调用JS代码把它在v8中履行,将成果回来到写diamagnetic的当地
整个进程咱们发现:V8 和 libuv是最重要的,而Node.js中的bindings / API 便是V8 和 libuv 中心的桥梁,咱们写的代码仅仅整个渠道中很小的一部分,这便是Node.js的作业流程
咱们写的代码 ==> V8上运转 ==> V8经过Node.js的bindings/API ==> 运用libuv供给的功用 / 其他的C++供给的功用完结用户所需求的功用
因而说Node.js不是一门言语,也不是一个结构,它便是一个渠道!!!
Node.js API与学习思路
接下来咱们只需求架构图中最上面的一块 Node.js API(官方供给的函数)
API文档
官方地址
- 英文文档 nodejs.org/api/
- 中文文档 nodejs.cn/api/
这些文档更像是字典,实在是太多了,没有欲望经过阅读文档去学习
民间版别(引荐)
- devdics.io: devdocs.io/
- 进入之后敞开Node.js 10 LTS
- 搜索功用十分便利
- 可敞开主题
- 可离线观看
API到底有哪些功用
重点关注黄色标示的API
- Buffer: 一小段缓存(大文件一点一点上传)
- Child Processes: 子进程(Node.js的分身)
- Cluster: 集群 (把多个Node.js集合到一起,每个Node.js做不同的工作,它们之间的联系便是主要和非必须的联系)
- Debugger: 调试
- Events: 对应的便是EventHub,发布订阅模式(一个目标供给了on、off、emit)
- File System: 文件体系,操作文件/目录
-
Globals: 全局变量,如:
__dirname:当时文件所在目录;__filename: 当时文件的文件名
- Http
- Path: 途径
- Query Strings: 处理URL
- Stream: 流格式的数据的处理
- Timers: settimeout 、setInterval、setImmediate
- URL
- Worker Threads*
学习路线
根底 – Web – 结构
- 先学根底,以使命为导向学习
- 逐个学习文件、HTTP、Stream等模块
- 在学Web、数据库、AJAX相关知识
- 最后学习结构,以项目为导向
- 以Express为切入点,制造完整网站
约定
- 记笔记,写博客
- CRM学习法贯穿整个学习进程(copy => run => modify,学习任何技能最快的方法)
- 学习调试东西和思路