JavaScript单线程与浏览器多线程
- Javascript是单线程的:由于JS运转在浏览器中,是单线程的,每一个window一个JS线程。作为浏览器剧本言语,JavaScript的主要用途是与用户互动,以及操纵DOM。若以多线程的体式格局操纵这些DOM,则可以涌现操纵的争执。假设有两个线程同时操纵一个DOM元素,线程1要求浏览器删除DOM,而线程2却要求修正DOM款式,这时刻浏览器就没法决议采纳哪一个线程的操纵。
浏览器不是单线程的,引擎可以存在以下线程:
- javascript引擎线程
- 界面衬着线程
- 浏览器事宜触发线程
- Http要求线程等
Event Loop
事宜轮回机制:
主线程从”使命行列”中读取事宜,这个历程是轮回不断的,所以全部的这类运转机制又称为Event Loop(事宜轮回)。主线程运转的时刻,发作堆(heap)和栈(stack),栈中的代码挪用种种外部API,它们在”使命行列”中到场种种事宜(click,load,done)。只需栈中的代码实行终了,主线程就会去读取”使命行列”,顺次实行那些事宜所对应的回调函数。
- 实行栈:一切同步使命都在主线程上实行,构成一个实行栈;
- 使命行列:主线程之外,还存在一个”使命行列”(task queue)。只需异步使命有了运转效果,就在”使命行列”当中安排一个事宜,当栈为空时,就会从使命行列中掏出一个使命并实行。
定时器:
定时器包括setTimeout与setInterval两个要领。它们的第二个参数是指定其回调函数推延每隔若干毫秒数后实行。
零耽误 setTimeout(func, 0):零耽误并非意味着回调函数马上实行。它取决于主线程当前是不是余暇与“使命行列”里其前面正在守候的使命。当计时器时候划定的时刻,回调函数会被添加到“使命行列”中,比及实行栈的使命实行终了,就会来实行这里的使命。所以,有的时刻纵然计时器已到0了,也会不马上实行计时器中的回调使命。
Ajax异步要求:
在提议ajax要求的时刻,浏览器会开一个线程去实行这一步骤,发要求这一步是属于实行栈中的同步使命,在要求发完以后就会实行栈中的下一个使命,而比及要求有了效果,就会把效果放入“使命行列”中,守候实行;
JavaScript异步编程
JavaScript是单线程的,所谓“单线程”,就是同一时候只能实行一个使命。假如有多个使命,就必须列队,直到前一个使命完成。这类情势的优点就是完成比较简朴,尤其在浏览器环境中,可以防止很多不必要的贫苦。害处就是假如一个使命耗时很长,那末该使命背面的使命就必须一向守候,致使全部页面都卡住没法继承往下实行。
为了处理这个题目,JavaScript将使命的实行情势分为两类,一个是同步情势,另一个是异步情势。
“同步情势”就是上一段的情势,后一个使命守候前一个使命完毕,然后再实行,递次的实行递次与使命的分列递次是一致的、同步的;”异步情势”则完全差别,每一个使命有一个或多个回调函数(callback),前一个使命完毕后,不是实行后一个使命,而是实行回调函数,后一个使命则是不等前一个使命完毕就实行,所以递次的实行递次与使命的分列递次是不一致的、异步的。
JS异步编程的4中要领包括:
回调函数:
f1(); f2(); function f1(callback){ setTimeout(function(){ callback(); }) } f1(f2);
事宜监听:采纳事宜驱动情势。使命的实行不取决于代码的递次,而取决于某个事宜是不是发作。
//jQuery f1.on('done', f2); function f1(){ setTimeout(function () { //do something f1.trigger('done');//实行完成后,马上触发done事宜,从而最先实行f2。 }, 1000); }
宣布/定阅:又称观察者情势
jQuery.subscribe("done", f2);//定阅'done'这个信号 function f1(){ setTimeout(function () { //do something jQuery.publish("done");//f1()实行完以后,发出'done'这个信号,f2最先实行 }, 1000); } jQuery.unsubscribe("done", f2);//作废定阅
Promises:ES6原生供应了Promise对象。所谓Promise对象,就是代表了将来某个将要发作的事宜(通常是一个异步操纵)。它的优点在于,有了Promise对象,就可以将异步操纵以同步操纵的流程表达出来,防止了层层嵌套的回调函数。别的,Promise对象还供应了一整套完全的接口,使得可以越发轻易地掌握异步操纵。
var promise = new Promise(function(resolve, reject) { if (/* 异步操纵胜利 */){ resolve(value); } else { reject(error); } }); promise.then(function(value) { // success }, function(value) { // failure });
ES6模块治理
ECMAScript 6基于export和import,定义了模块的导出和导入范例,在言语规范层面完成了模块机制。该规范的目的是建立一种可以兼容CommoneJS和AMD两规范的范例,即可以像CommoneJS一样语法简约、运用单一的接口且支撑轮回依靠,又可以像AMD支撑异步加载和可设置的模块加载。
大抵来说,当 JS 引擎运转一个模块的时刻,它的行动大抵可归结为以下四步:
- 剖析:引擎完成会浏览模块的源码,而且搜检是不是有语法错误。
- 加载:引擎完成会(递归地)加载一切被引入的模块。
- 链接:引擎完成会为每一个新加载的模块建立一个作用域,而且将模块中的声明绑定填入个中,包括从其他模块中引入的。
JS加载
动态加载经常使用的4种要领:
- document.write:
document.write("<script src='package.js'><\/script>");
- 动态转变已有script的src属性:
js.src = "package.js";
动态建立script元素:
var script = document.createElement("script"); script.src = "XXX"; script.type = "XXX"; document.head.appendChild(script);
- 用XMLHTTP取得要剧本的内容,再建立 Script 对象。
项目中加载JS的要领:
在页面底部写一个自挪用函数,加载进口JS,然后进口中的要领实行,加载须要的其他JS。
<script>
(function(G,D){var el=D.createElement('script'),d="XXX';
el.src=((G._moduleConfig&&G._moduleConfig.domain)?G._moduleConfig.domain:d)+"XXX?t=XXX";
D.getElementsByTagName('head')[0].appendChild(el);
})(this,document);
</script>
在VM平台上,可以挑选将几个模块分组打包到一个进口文件中,然后在这个进口文件中,将每一个组动态天生一个script标签,插进去head中。
异步加载:
浏览器在衬着一个页面的时刻,碰到一个<script>
标签就会去下载对应的js文件,假如采纳同步加载JS的体式格局,会形成页面壅塞,直到JS加载完成再继承衬着,所以有了异步加载JS的情势。
罕见的异步加载JS体式格局,将js代码包裹在匿名函数中并马上实行,动态天生<script>
标签去拉取js,可以完成多个js文件并行下载,只要在剖析实行的时刻会壅塞衬着。别的,可以运用script标签的async
和defer
属性。
耽误加载:
耽误加载就是一最先并不加载这些临时不必的js,而是在须要的时刻或稍后再经由过程js 的掌握来异步加载。
也就是将 js 切分红很多模块,页面初始化时只加载须要马上实行的 js ,然后别的 js 的加载耽误到第一次须要用到的时刻再加载。
特别是页面有大批差别的模块构成,很多可以临时不必或根本就没用到。
script的两阶段加载与耽误实行
JS的加载实际上是由两阶段构成:下载内容(download bytes)和实行(parse and execute)。
浏览器在下载完 js 的内容后就会马上对其剖析和实行,不管是同步加载照样异步加载。
前面说的异步加载,处理的只是下载阶段的题目,但代码在下载后会马上实行。
而浏览器在剖析实行 JS 阶段是壅塞任何操纵的,这时刻的浏览器处于无相应状况。
我们都晓得经由过程收集下载 script 须要显著的时候,但轻易疏忽了第二阶段,剖析和实行也是须要时候的。script的剖析和实行所花的时候比我们设想的要多,尤其是script 很多很大的时刻。有些是须要马上实行,而有些则不须要(比方只是在展现某个界面或实行某个操纵时才须要)。
这些script 可以耽误实行,先异步下载缓存起来,但不马上实行,而是在第一次须要的时刻实行一次。
应用特别的技能可以做到下载与实行的星散。比方将 JS 的内容作为object对象加载缓存起来,所以就不会马上实行了,然后在第一次须要的时刻再实行。
SQL相干
多表查询:
- 定义:依据特定的衔接前提从差别的表中猎取所需的数据;
- 语法:
SELECT table1.column, table2.column FROM table1, table2 WHERE table1.column1 = table2.column2;
- 注重:where不要省了,省略where即为笛卡尔集,而且where前提要有效,两张表间有一个雷同的字段,才好举行有效的多表查询;
- 简化:为了简化SQL誊写,可为表名定义别号,花样:from 表名别号,如:from emp e,dept d;
- 优化:发起运用表的别号及表前缀,运用表别号可以简化查询,而运用表前缀则可以进步查询机能;
衔接范例:从数据显现体式格局来说有:内衔接和外衔接。
内衔接:只返回满足衔接前提的数据。
- 例:
select empno,ename,sal,dname,loc from emp,dept where emp.deptno=dept.deptno;
- 等值衔接:在衔接前提中运用即是号(=)运算符比较被衔接列的列值,其查询效果中列出被衔接表中的一切列,包括个中的重复列。
- 不等值衔接:在衔接前提运用除即是运算符之外的别的比较运算符比较被衔接的列的列值。这些运算符包括>、>=、<=、<、!>、!<和<>。
- 天然衔接:在衔接前提中运用即是(=)运算符比较被衔接列的列值,但它运用挑选列表指出查询效果鸠合中所包括的列,并删除衔接表中的重复列。
- 例:
外衔接:除了返回满足衔接条的行之外,还返回左(右)表中,不满足前提的行,称为左(右)衔接;
左外衔接:是以左表为基准,将左表没有的对应项显现,右表的列为NULL
select * from book as a left join stu as b on a.sutid = b.stuid
右外衔接:是以右表为基准,将a.stuid = b.stuid的数据举行衔接,然以将右表没有的对应项显现,左表的列为NULL
select * from book as a right join stu as b on a.sutid = b.stuid
全衔接:完全外部连接返回左表和右表中的一切行。当某行在另一个表中没有婚配行时,则另一个表的挑选列表列包括空值。假如表之间有婚配行,则全部效果集行包括基表的数据值。
select * from book as a full outer join stu as b on a.sutid = b.stuid
CI框架经常使用的数据库操纵:
- 通例查询:
$this->db->query('YOUR QUERY HERE');
- 查询绑定:查询绑定可以简化你的查询语法,它经由过程体系自动的为你将各个查询组装在一起。 参考下面的例子:
$sql = "SELECT * FROM some_table WHERE id = ? AND status = ? AND author = ?"; $this->db->query($sql, array(3, 'live', 'Rick'));
-
$this->db->count_all()
:该要领用于猎取数据表的总行数,第一个参数为表名; 查询组织器类:odeIgniter 供应了查询组织器类,查询组织器许可你运用较少的代码来在数据库中 猎取、新增或更新数据。偶然只须要一两行代码就可以完成数据库操纵。CodeIgniter 并不须要为每一个数据表供应一个类,而是运用了一种更简朴的接口。
- 查询:
$query = $this->db->get('mytable'); // Produces: SELECT * FROM mytable $query = $this->db->get('mytable', 10, 20); // Executes: SELECT * FROM mytable LIMIT 20, 10 // (in MySQL. Other databases have slightly different syntax)
-
$this->db->select()
:该要领用于编写查询语句中的 SELECT 子句:
$this->db->select('title, content, date'); $query = $this->db->get('mytable'); // Executes: SELECT title, content, date FROM mytable
-
$this->db->from()
:该要领用于编写查询语句中的 FROM 子句:
$this->db->select('title, content, date'); $this->db->from('mytable'); $query = $this->db->get(); // Produces: SELECT title, content, date FROM mytable
-
$this->db->join()
:该要领用于编写查询语句中的 JOIN 子句:
$this->db->select('*'); $this->db->from('blogs'); $this->db->join('comments', 'comments.id = blogs.id'); $query = $this->db->get(); // Produces: // SELECT * FROM blogs JOIN comments ON comments.id = blogs.id //你可以传入第三个参数指定衔接的范例,有如许几种挑选:left,right,outer,inner,left outer 和 right outer 。 $this->db->join('comments', 'comments.id = blogs.id', 'left'); // Produces: LEFT JOIN comments ON comments.id = blogs.id
-
$this->db->where()
:该要领供应了4中体式格局让你编写查询语句中的 WHERE 子句(一切的数据将会自动转义,天生平安的查询语句。):
1.简朴的 key/value 体式格局: $this->db->where('name', $name); // Produces: WHERE name = 'Joe' 注重自动为你加上了等号。 假如你屡次挪用该要领,那末多个 WHERE 前提将会运用 AND 衔接起来: $this->db->where('name', $name); $this->db->where('title', $title); $this->db->where('status', $status); // WHERE name = 'Joe' AND title = 'boss' AND status = 'active' 2.自定义 key/value 体式格局: 为了掌握比较,你可以在第一个参数中包括一个比较运算符: $this->db->where('name !=', $name); $this->db->where('id <', $id); // Produces: WHERE name != 'Joe' AND id < 45 3.关联数组体式格局: $array = array('name' => $name, 'title' => $title, 'status' => $status); $this->db->where($array); // Produces: WHERE name = 'Joe' AND title = 'boss' AND status = 'active' 你也可以在这个要领里包括你本身的比较运算符: $array = array('name !=' => $name, 'id <' => $id, 'date >' => $date); $this->db->where($array); 4.自定义字符串: 你可以完全手工编写 WHERE 子句: $where = "name='Joe' AND status='boss' OR status='active'"; $this->db->where($where); $this->db->where() 要领有一个可选的第三个参数,假如设置为 FALSE,CodeIgniter 将不庇护你的表名和字段名。 $this->db->where('MATCH (field) AGAINST ("value")', NULL, FALSE);
-
$this->db->like()
:该要领用于天生 LIKE 子句,在举行搜刮时异常有效。
简朴 key/value 体式格局: $this->db->like('title', 'match'); // Produces: WHERE `title` LIKE '%match%' ESCAPE '!' 假如你屡次挪用该要领,那末多个 WHERE 前提将会运用 AND 衔接起来: $this->db->like('title', 'match'); $this->db->like('body', 'match'); // WHERE `title` LIKE '%match%' ESCAPE '!' AND `body` LIKE '%match% ESCAPE '!' 可以传入第三个可选的参数来掌握 LIKE 通配符(%)的位置,可用选项有:'before','after' 和 'both' (默以为 'both')。 $this->db->like('title', 'match', 'before'); // Produces: WHERE `title` LIKE '%match' ESCAPE '!' $this->db->like('title', 'match', 'after'); // Produces: WHERE `title` LIKE 'match%' ESCAPE '!' $this->db->like('title', 'match', 'both'); // Produces: WHERE `title` LIKE '%match%' ESCAPE '!' 关联数组体式格局: $array = array('title' => $match, 'page1' => $match, 'page2' => $match); $this->db->like($array); // WHERE `title` LIKE '%match%' ESCAPE '!' AND `page1` LIKE '%match%' ESCAPE '!' AND `page2` LIKE '%match%' ESCAPE '!'
-
$this->db->group_by()
:$this->db->group_by("title"); // Produces: GROUP BY title;
-
$this->db->order_by()
:$this->db->order_by('title', 'DESC');
-
$this->db->limit()
:$this->db->limit(10); // Produces: LIMIT 10
-
$this->db->count_all_results()
:该要领用于猎取特定查询返回效果的数目,也可以运用查询组织器的这些要领:where(),or_where(),like(),or_like()
等等。 -
$this->db->delete()
:$this->db->delete('mytable', array('id' => $id)); // Produces: // DELETE FROM mytable // WHERE id = $id
- 通例查询:
为何chrome浏览器的速率很快
- Chrome 把浏览器上做的每件事都拆成自力的历程,每一个tab都是一个自力的历程,并应用历程间通讯来完成它们之间的同步,windows体系下可以经由过程使命治理器看到很多chrome 标签页的历程。
- 在还没点击 URL 之前,Chrome 已在帮用户加载了
参考文章:
JavaScript的加载和实行机能优化
Javascript 异步加载详解
ES6 的模块体系
seaJs进修笔记之seaJs的异步加载和加载多个js文件
Promise对象
Javascript异步编程的4种要领
JavaScript 运转机制详解:再谈Event Loop
JavaScript:完全明白同步、异步和事宜轮回(Event Loop)
JavaScript单线程和浏览器事宜轮回简述
Javascript是单线程的深入分析
查询辅佐函数
SQL的几种衔接:内衔接、左连接、右衔接、全衔接、交织衔接
SQL基本–>多表查询
CHROME历程间通讯
浏览器是如何事情的
浏览器是如何事情的:衬着引擎,HTML剖析
等……