js 是一门单线程语言,什么是单线程呢?
单线程指同一时间,只能同时执行一个任务,在上一个任务结束之后才能进行下一个任务的执行。这意味着,Js的执行是同步的,顺序性地执行,就像一条直线,从头跑到尾。那么,如果某一个任务需要很长的执行时间,这个任务下面的所有任务都需要等待这个任务完成才能执行,就会造成运算能力和时间的浪费。这时候,异步的作用就体现出来了。
异步(asynchronous)是一种程序执行机制,用于将某个方法暂时挂起,在某个事件被触发之后再执行该方法。
"回调函数"(callback),就是那些会被主线程挂起来的代码。异步任务必须指定回调函数,当主线程开始执行异步任务,就是执行对应的回调函数。
JS异步编程:
setTimeout()
事件驱动
ajax 请求:new XMlHttpRequest();
异步执行的运行机制如下。
(1)所有同步任务都在主线程上执行,形成一个执行栈(execution context stack)。
(2)主线程之外,还存在一个"任务队列"(task queue)。只要异步任务有了运行结果,就在"任务队列"之中放置一个事件。
(3)一旦"执行栈"中的所有同步任务执行完毕,系统就会读取"任务队列",看看里面有哪些事件。那些对应的异步任务,于是结束等待状态,进入执行栈,开始执行。
(4)主线程不断重复上面的第三步。
Js 引擎线程中,有 堆(heap)和栈(stack),栈中存放的就是当前 Js 程序运行的所有同步任务,也就是说,这是一个 执行栈。
在 Js 引擎线程的机制中,只会一直运行 栈(stack) 中的任务,当栈(stack) 中的任务全部运行完成后,Js 引擎线程就会读取 callback-queue(消息队列、任务队列) 中的任务,然后将callback-queue(消息队列、任务队列) 的任务放到 栈(stack)执行,一直这样循环,直到 栈(stack) 和 callback-queue(消息队列、任务队列)中都没有任务为止。这称之为 event-loop,也就是中文翻译的 “事件轮询”。
setTimeout()只是将事件插入了"任务队列",必须等到当前代码(执行栈)执行完,主线程才会去执行它指定的回调函数。要是当前代码耗时很长,有可能要等很久,所以并没有办法保证,回调函数一定会在setTimeout()指定的时间执行。
异步就可以看成是 回调函数和事件的组合。在某个方法中,定义一个回调函数和触发事件,当触发事件的时候,就执行回调函数
异步任务与event-loop
Event Loop(事件循环),它总是循环的查找任务队列里是否还有任务,以异步的方式将任务的执行结果返回给V8引擎。
V8引擎再将结果返回给用户。
===============================================================
Chrome :多线程
(1) JS单线程
(2)DOM,CSS 渲染线程
....
NOde.js
(1) JS单线程
观察者模式
当对象间存在一对多关系时,则使用观察者模式(Observer Pattern)。比如,当一个对象被修改时,则会自动通知它的依赖对象。观察者模式属于行为型模式。
优点: 1、观察者和被观察者是抽象耦合的。 2、建立一套触发机制。
===============================================================
Node事件的工作原理
1. 为某个对象绑定事件(通过on这个方法绑定),也可以理解为为某个对象添加一个或多个观察者(通过callback设定事件,即回调方法),来观察这个对象的动作
2. 这个对象在某个状态或操作下,触发事件,或者说激活观察者行为(通过emit激活某类事件或观察者)
3. 被激活的事件执行相应的处理(执行callback方法)
===============================================================
(1) 提醒:File->Setting->Language & Framework->
js/Library: + 添加下载的Node源码(43M左右,解压即可,Node源码在103上,版本10.16)
con:editor->live Templates->javascript->+,live Template、
快捷键
con
console.log('$PARAM$')
-->勾下生成范围:javascript
(2)事件就是需要 eventEmitter.on() 去绑定一个事件, 通过 eventEmitter.emit() 去触发这个事件.
其次说的是 事件的 调用 和 接收 是分开的.
就像 一个外卖店你可以不停的接受很多订单, 接受以后开始告诉厨师去做外卖, 做好的外卖对应的外送给每个用户,如果单线程的话那只能是接收一个订单, 做好以后在接收下一个外卖订单,明显效率非常低。
事件可以不停的接受不停的发生也是为了提高效率。
eventEmitter.emit 是触发事件(事件请求),eventEmitter.on是绑定处理事件的处理器(事件处理),事件的请求和处理是分开的,所以是异步。
(3)一个js 文件就是一个模块,exports
exports和require两个对象
https://nodejs.org/en/download/
events.js
function EventEmitter() {
EventEmitter.init.call(this);
}
module.exports = EventEmitter;
=======================
var events=require('events');
var eventEmitter=new events.EventEmitter();
=======================
原生模块
原生模块缓存
文件模块
文件模块缓存
require("http.js")--> 内存(“文件模块缓存”)-->“原生模块”?--->否 -->“文件模块”查找-->缓存文件模块
--->是-->原生模块中缓存区查找->加载原生模块-->-->缓存原生模块
加载模块的效率:
文件模块 最低
原生模块 低
文件模块缓存 高
原生模块缓存 最高
require events,fs,stream,buffer,http,net,path,url,util
(4)全局作用域
全局对象 ,函数或类,变量、
module.exports
exports.
require()
setIntervalOut()...
全局对象是global
以模块为单位 ,尽量减少全局变量的使用;
require. cache对象
全局变量:__filename变量与__dirname变量
(5)***文件读取 fs
异步readfile
同步readfilesync
写入文件writefile
删除文件unlink
流
管道
var fs =require('fs');
///////////////////////////管道////////////////
var wstream =fs.createWriteStream('');
var datas='123456';
wstream.write(datas,'utf8')
wstream.on('finish',function () {
console.log("成功");
})
wstream.on('error',function (err) {
console.log(err);
})
stream.pipe(wstream);
===============get请求===================
===============post请求==================
var qs=require('querystring’);
用querystring模块将post的数据变为对象 然后取出
================mvc==============
1.view
为html页面
2.router
为配置路由
pathname为 url.parse(req.url,ture).pathname
index(/public)为配置所有静态资源
余下为配置路径
3.controller层为对应页面具体实现和一些功能实现方法
此为显示html页面
此为数据库的修改
查询数据库
查询用到了ejs模版
数据库删除操作
数据库添加操作
4.myutil
工具包
其中有连接池 为controller层提供数据库连接