Git Product home page Git Product logo

blog's People

Contributors

zyuming avatar

Stargazers

 avatar

Watchers

 avatar  avatar  avatar

Forkers

18252779313

blog's Issues

JS的事件循环机制

前言

先来个🌰,执行下面代码,输出的顺序是怎样的?

console.log('script start')
setTimeout(function() {
  console.log('setTimeout')
}, 0)
Promise.resolve().then(function() {
  console.log('promise1')
}).then(function() {
  console.log('promise2')
});

console.log('script end')

正确答案是script start, script end, promise1, promise2, setTimeout

要想弄不明白为什么是这顺序,你需要知道事件循环(Event Loop)是如何处理微任务(Micro Task)跟宏任务(Macro Task)

事件循环(Event Loop)

事件循环就是个循环,其不断检查是否有有事件待处理,如果有就处理该事件。如果没有则进入下一个循环。在每个循环中通过观察者模式来说判断是否有事件需要处理。事件的顺序决定了js代码的执行顺序。

任务

同步任务 即可以立即执行的任务,如console.log打印一条日志、声明一个变量或者执行一次加法等
异步任务 不会立即执行的事件任务,包括宏任务和微任务

宏任务(Macro Task)

不会导致页面渲染的阻塞

script(全局任务), setTimeout, setInterval, setImmediate, I/O, UI rendering

微任务(Micro Task)

会影响页面渲染

process.nextTick, promise.then(), object.observe, MutationObserver

执行顺序

回到实例

console.log('script start')
setTimeout(function() {
  console.log('setTimeout')
}, 0)
Promise.resolve().then(function() {
  console.log('promise1')
}).then(function() {
  console.log('promise2')
});

console.log('script end')
  1. 代码运行到console.log('script end')时
macro queue: ['Run script', 'setTimeout callback']
micro queue: ['Promise then']
stack: ['script']
log: ['script start', 'script end']
  1. 运行到console.log('promise2')时
macro queue: ['Run script', 'setTimeout callback']
micro queue: ['Promise then']
stack: ['Promise callbak']
log: ['script start', 'script end','promise1', 'promise2']
  1. 运行到console.log('setTimeout')时
macro queue: ['setTimeout callback']
micro queue: []
stack: ['setTimeout callback']
log: ['script start', 'script end','promise1', 'promise2', 'setTimeout']
  1. 结束
macro queue: []
micro queue: []
stack: []
log: ['script start', 'script end','promise1', 'promise2', 'setTimeout']

centOS7.0 搭建FTP服务器

前言

  为了做毕业设计,特地去买了个阿里云的服务器。一开始贪方便选择了Windows Server 2008操作系统,毕竟用惯了windows的界面操作,用了一周后发现系统老是出现各种各样的问题(= =)就换成了centOS系统。换了系统,第一件麻烦事就是如何搭建ftp服务器来上传项目文件和配合sublimeText里面的SFTP插件进行开发。

安装vsftp:

yum install vsftpd -y


编辑ftp配置文件:

文件所在位置 : /etc/vsftpd/vsftpd.conf

开启anonymous_enable

anonymous_enable=NO
#anonymous_enable=YES
chroot_local_user=YES

去掉前面的注释(不受限制的用户列表)

#chroot_list_enable=YES
#chroot_list_file=/etc/vsftpd/chroot_list

加上这行解决了无法登陆的问题

allow_writeable_chroot=YES

修改FTP的Selinux设置

setsebool -P ftp_home_dir=1
sersebool -P allow_ftpd_full_access=1


防火墙的设置

关闭关闭防火墙

service iptables stop

防火墙配置

iptables -A INPUT -p tcp --dport 21 -j ACCEPT
iptables -A INPUT -p tcp --dport 20 -j ACCEPT

在/etc/sysconfig/system-firewall-config中添加

--service=ftp


建立FTP账户

建立账号

useradd -d /path/you/want -s /sbin/nologin ftpadmin

修改密码

passwd ftpadmin

设置账户权限

chown -R ftpadmin.ftpadmin /path/you/set


启动/重新启动FTP

service vsftpd start
service vsftpd restart

JS创建对象模式

前言

  随着Node和JS模块化工程的兴起,而Javascript模块对应的就是一个个对象,因此如何处理对象也变得尤为重要。对象的创建是对象处理的第一步,故总结了以下几种常见的对象创建模式。

工厂模式

function createPerson(name, age, job){
  var o = new Object();
  o.name = name;
  o.age = age;
  o.job = job;
  o.sayName = function(){
    alert(this.name);
  } 
  return o;
}
var person1 = createPerson("Ming", 23, "Software Enginner");
var person2 = createPerson("Yu", 22, "Doctor");

优点: 解决了创建多个相似对象的问题
缺点: 对象识别问题(即怎样知道一个对象的类型)


构造函数模式

function Person(){};
Person.prototype = {
  name : "Ming",
  age  : 23,
  job  : "Software Enginner",
  sayName : function() {
    alert(this.name);
  }
};
var person1 = new Person();
var person2 = new Person();

优点: 解决了每个方法都要在每个实例上重新创建一遍问题
缺点: 原型模式省略了构造函数传递初始化参数的环节,结果所有实例在默认情况下都将取得相同的属性值,而且原型中所有的属性是被很多实例共享的,这种共享适合于函数,并不适合属性


组合使用构造函数模式和原型模式

function Person(name, age, job){
  this.name = name;
  this.age = age;
  this.job = job;
  this.friends = ["Shelby","Court"];
}
Person.prototype.sayName = function() {
  alert(this.name);
};  
var person1 = new Person("Ming", 23, "Software Enginner");
var person2 = new Person("Yu", 22, "Doctor");

优点: 构造函数模式用于定义实例属性,而原型模式用于定义方法和共享的属性。是目前使用最广泛,认同度最高的一种创建自定义类型的方法。


动态原型模式

function Person(name, age, job){
  this.name = name;
  this.age = age;
  this.job = job;
  this.friends = ["Shelby","Court"];
  if(typeof this.sayName != "function"){
    Person.prototype.sayName = function() {
      alert(this.name);
    };
  }  
}
var person1 = new Person("Ming", 23, "Software Enginner");

优点:可以通过检测某个应该存在的方法是否有效,来决定是否需要初始化实例。如只在sayName不存在的情况下,才会将它添加到原型中,而且这段代码只会在初次调用构造函数时才会执行,此后,原型已经初始化完成,不需要再做什么修改了。


稳妥构造函数模式

function Person(name, age, job){
  var o = new Object();
  o.sayName = function(){
    alert(name);
  };
  return o;
}
var friend = new Person("Ming", 23, "Software Enginner");
friend.sayName();

*稳妥对象:没有公共属性,其方法也不引用this的对象。
优点:变量friend中保存的是一个稳妥对象,除了调用sayName()方法以外,没有别的方式可以访问其他数据成员。

对于BFC的理解

何为BFC?


BFC(Block formatting context)直译为”块级格式化上下文”。它是一个独立的渲染区域,只有Block-level box参与, 它规定了内部的Block-level Box如何布局,并且与这个区域外部毫不相干。
跟BFC相关的概念有Box,Formatting Conetxt

Box

Box是CSS布局的基本单位,分为block-level box和inline-level box,不同类型的Box,会参与不同的Formating。
block-level box:当display为block, list-item, table的元素
inline-level box:当displayinline, inline-block, inline-table的元素

Formatting context

Formatting context是页面中的一块渲染区域,并且有一套渲染规则,决定其子元素将如何定位,以及其他元素的关系和相互作用。
常见的Formatting context的有Block fomatting context (简称BFC)和 Inline formatting context (简称IFC)。

触发BFC

  • 根元素
  • float属性不为none;
  • position为absolute或fixed
  • display为inline-bolck,table-cell,table-caption,flex,inline-felx
  • overflow不为visible

BFC规则


  • 内部的Box会在垂直方向,一个一个地放置(也可以在水平方向)
  • Box的距离由margin决定,属于同一个BFC的两个相邻的Box的margin会发生重叠
  • 每个元素的margin box的左边, 与包含块border box的左边相接触(对于从左往右的格式)。即使存在浮动也是如此
  • BFC的区域不会与float box重叠
  • BFC就是页面上的一个隔离的独立容器,容器里面的子元素不会影响到外面的元素
  • 计算BFC的高度时,浮动元素也参与计算

BFC的用途


自适应两栏布局

利用BFC规则BFC的区域不会与float box重叠。触发右边的元素生成BFC,来实现两栏布局。
HTML:

<body>
  <div class="aside"></div>
  <div class="main"></div>
</body>

CSS:

html{
  height: 100%;
}
body{
  margin: 0;
  padding: 0;
  width: 100%;
  height: 100%;
  position: relative;
  overflow: hidden;
}	
.aside{
  width: 300px;
  height: 100%;
  float: left;
  background: #f66;
}
.main{
  height: 100%;
  background: #fcc;
  overflow: hidden;
}

清除浮动

利用BFC规则计算BFC的高度时,浮动元素也参与计算。通过overflow: hidden触发父元素生成BFC
HTML:

<div class="out">
  <div class="in1"></div>
  <div class="in2"></div>
</div>

CSS:

.out{
  width: 500px;
  background-color: #666;
  overflow: hidden;
}
.in1{
  width: 100px;
  height: 100px;
  float: left;
  background-color: #999;
}
.in2{
  width: 100px;
  height: 100px;
  float: left;
  background-color: #ccc;
}

防止margin重叠

利用BFC规则Box垂直方向的距离由margin决定。属于同一个BFC的两个相邻Box的margin会发生重叠算,我们可以在一个元素外面包裹一层容器,并处罚金该容器生成一个BFC。则和相邻元素不属于同一个BFC,就不会发生margin重叠了。
HTML:

<p>Haha</p>
<div class="wrap">
  <p>Hehe</p>
</div>

CSS:

.wrap{
  overflow: hidden;
}
p{
  background-color: #333;
  width: 200px;
  margin: 100px;
}

[译] 浏览器内部揭秘(2)

原文链接:
Inside look at modern web browser (part 2)

导航是发生什么

这是浏览器内部揭秘博客系列的第2部分。在上一篇文章中,我们研究了不同的进程和线程如何处理浏览器任务的。在这篇文章中,我们将深入研究渲染网站的进程和线程如何进行通信。

让我们看一下浏览器的常见用法:你在地址栏上输入URL,然后浏览器去拉取数据并显示在页面。在这篇文章中,我们将重点关注用户如何访问网站以及浏览器如何呈现页面 - 也称为导航。

先从浏览器进程讲起

正如我们在第1篇文章所述一样,选项卡外部的任务都是由浏览器进程来处理的。浏览器进程具有用于绘制浏览器的按钮和输入框等的UI线程,处理网络堆栈以从互联网接收数据的网络线程,处理对文件的访问的存储线程等。当你在地址栏中输入URL时,浏览器进程的UI线程将会处理你的输入。

browserprocesses
图1:浏览器UI线程,网络线程和存储线程图

一个简单的导航例子

1:处理输入

当用户在地址栏输入信息时,UI线程首先会判断用户输入的是搜索查询还是URL?判断出来后便将你输入的信息发送到搜索引擎或者发送到你请求的网站。

input
图2:UI线程判断输入信息是搜索查询还是URL

2:开始导航

当用户点击确认时,UI线程发起获取网站内容的请求。加载菊花图将出现在选项卡上,网络线程选择合适的协议去请求,如DNS查找或建立TLS连接。

navstart
图3:UI线程通知网络线程去请求mysite.com

此时,网络线程可能接收到HTTP 301这样的服务器重定向头信息。在这种情况下,网络线程将通知UI线程服务器请求重定向的信息。然后,将启动另一个URL请求。

3:解析响应包

一旦开始接收响应主体,网络线程会检查流的前几个字节。响应包的Content-Type标头应该说明它是什么类型的数据,但由于该字段可能丢失或错误,所以还需要进行MIME类型嗅探操作。这是特别繁琐的一个步骤。

response
图4:header是请求的响应头以及payload是响应内容

如果响应内容是HTML文件,那么下一步就是将HTML文件传递给渲染器进程,但如果它是zip文件或其他文件,则表示它是下载请求,则将改数据传递给下载管理器。

sniff
图5:网络线程将去询问响应数据HTML文件是否来自于安全站点

这也是SafeBrowsing该检查的内容。如果网站或者响应的数据跟已知的恶意网站匹配,则网络线程会发出警告。此外,还会进行跨源读取阻止(CORB)检查,这是为了确保敏感的跨站点数据不会进入渲染进程。

4:渲染进程

当完成所有检查后,网络线程会告知UI线程数据已准备就绪。然后,UI线程找到渲染进程以进行网页渲染。

findrenderer
图6:网络线程通知UI线程数据已准备就绪

由于网络请求可能需要几百毫秒才能得到响应。所以当UI线程在步骤2中向网络线程发送URL请求的同时,UI线程会尝试主动查找并启动渲染进程。这样,如果一切按预期进行,则当网络线程接收数据时,渲染进程已处于备用状态。但如果导航需要重定向,则可能不会使用此渲染进程,在这种情况下可能需要不同的进程来配合。

5:提交导航

数据和渲染进程已准备就绪了,浏览器进程发送一个IPC通知渲染进程开始工作,同时浏览器进程还会把数据传递给渲染进程。
一旦浏览器进程确认渲染进程已经准备就绪,导航动作就完成了,开始进入文档加载阶段了。这这个阶段,地址栏会更新,安全指示器和站点设置将会反映新页面的站点信息。选项卡的会话历史记录,后退/前进按钮也将会更新,会话历史记录也将存储在磁盘上方便后续进行会话还原。

commit
图7:浏览器进程发送一个IPC通知渲染进程进行渲染

6:初始加载完成

提交导航后,渲染进程将加载资源并呈现页面。我们将在下一篇文章中着重介绍这阶段。当渲染进程完成渲染后,它就会将发送一个IPC回浏览器进程(在页面上所有frames的onload事件都已经触发后)。此时,UI线程会停止选项卡上的加载菊花图。

渲染完成后客户端仍然可以加载额外的资源并呈现新的视图。
loaded
图8:渲染进程将发送一个IPC到浏览器进程通知页面已“加载”

导航到其他站点

上面了解了一个简单导航的流程!此时用户再次输入不同的URL放到地址栏会发生什么呢?浏览器进程会进行上面的步骤导航到不同的站点,但在这之前,浏览器进程还想需要处理当前站点事情,如果该站点有使用beforeunload事件的话。
beforeunload可以用来弹出“离开这个网站吗?”提示框。浏览器进程必须在新导航请求进入时检查当前渲染进程是有�必要的,因为选项卡内的所有内容包括JavaScript代码都由是渲染进程来处理的。

警告:不要滥用beforeunload事件。它会产生更多延迟,因为必须处理完beforeunload里面的代码才能启动新的导航。因此应只有必要的情况才应使用该事件,例如,如果需要警告用户他们可能会丢失他们在页面上输入的表单数据。

beforeunload
图9:浏览器进程发送IPC通知渲染器进程将要导航到另一个站点

如果导航是从渲染进程发起的(如用户点击链接或客户端JavaScript执行window.location =“https://newsite.com”),则渲染进程首先检查beforeunload事件。然后,走浏览器进程发起导航相同的流程。唯一的区别是导航请求从渲染进程传递到浏览器进程。

当新导航进入站点与当前渲染站点不一致时,新导航站点将调用单独的渲染过进程来处理,同时保持当前站点的渲染进程以处理unload等事件。有关更多信息,请参阅页面生命周期概述以及如何使用Page Lifecycle API钩子事件。

unload
图10:浏览器进程将发送两个IPC,一个通知新�渲染进程渲染页面,一个告知旧渲染进程进行卸载页面

服务工作线程(Service Worker)

最近chrome对该导航过程进行了改动,引入了服务工作线程。服务工作线程是一种在应用程序代码中编写网络代理的方法,它允许Web开发人员更好地控制本地缓存内容以及何时从网络获取新数据。如果将服务工作线程设置为从缓存加载页面,则无需从网络请求数据。

要重点关注的是服务工作线程是在渲染进程中运行的JavaScript代码的。但是当导航请求进入时,浏览器进程如何知道该站点有服务工作线程呢?

注册服务工作线程时,将保留服务工作线程的范围作为参考(您可以在此“服务工作线程生命周期”一文中阅读有关范围的更多信息)。当导航发生时,网络线程根据注册的服务工作线程范围的域进行检查,如果为该URL注册了服务工作线程,则UI线程找到渲染器进程以执行服务工作线程代码。服务工作线程可以直接从缓存中加载数据或者可从网络请求新资源。

scope_lookup
图11:浏览器进程中的网络线程查找服务工作线程的范围

serviceworker
图12:浏览器进程中的UI线程启动渲染进程以启动服务工作线程;然后,渲染进程中的服务工作线程通过网络线程请求数据

导航预加载

你可以看到,如果服务工作线程决定从网络请求数据时,可能会导致浏览器进程和渲染进程之间的通信延迟。导航预加载是一种通过与服务工作线启动并行加载资源来加速此过程的机制。可以用header标记这些请求,允许服务器决定为这些请求发送不同的内容,例如只更新数据而不是完整文档。

navpreload
图13:浏览器进程中的UI线程启动渲染进程的同时也启动网络线程

总结

在这篇文章中,我们研究了导航的步骤以及响应头,客户端JavaScript等Web应用程序代码是如何与浏览器交互。了解浏览器通过网络获取数据的步骤,可以更好地理解为什么需要导航预加载等的API。在下一篇文章中,我们将深入探讨浏览器如何把HTML / CSS / JavaScript代码呈现到页面。

Druid - 海量数据实时OLAP分析系统

Druid介绍

什么是Druid

Druid 是一个开源的,能在海量时序数据上 (万亿级别数据量, 1000 TB级别数据)上面提供实时分析查询的OLAP数据仓库,Druid提供了廉价的实时数据插入和任意数据探索的能力。美国公告技术公司MetaMarkets于2011年创建了该项目。
*(阿里也有个开源的数据链接池项目叫作Druid,两者没有任何关系,他们解决完全不同的问题。建议用“druid.io”关键字搜索该项目的信息

用来解决什么问题

1.RDBMS的查询速度太慢

RDBMS全表扫描操作响应特别慢,对于一个三千多万的数据,计算总行数需要3秒时间。所有列的处理方式相同。这意味着时间,维度,指标不做任何区分。因此使用这些数据的时候,需要管理哪些是维度,哪些是指标列。

2.支持灵活的查询的查询分析能力

Druid的特点

1.数据吞吐量大

很多公司选择Druid作为分析平台,都是看中Druid的数据吞吐能力。每天处理几十亿到几百亿的事件,对于Druid来说是非常适合的场景,目前已被大量互联网公司实践。因此,很多公司选择Druid是为了解决数据爆炸的问题。

2.支持流式数据摄入

很多数据分析软件在吞吐量和流式能力上做了很多平衡,比如Hadoop更加青睐批量处理,而storm则是一### 3.查询灵活且快
数据分析师都是希望从不同角度去分析数据。数据量小的时候,一切安好,但是数据量变大之后,不能秒级返回结果的分析系统都是被垢病的对象。因此,Druid支持任何维度组合上的进行查询,访问速度极快,这也是Druid作为分析平台最重要的两个杀手锏。

4.社区支持力度大

Druid开源后,受到不少互联网公司的青睐,包括雅虎,eBay,阿里巴巴等。MetaMarkets的几个Druid的发明人也成立了一家叫作Imply.io的新公司,推动Druid的生态发展。

Druid数据的存储结构

Druid采用的是基于DataSource与Segment的的数据结构,这也是成就Druid的高性能优势的之一。

1.DataSource结构


时间列(timestamp): 表明每行数据的时间值,默认使用UTC时间格式,精确到毫秒级别。 数据聚合与范围查询的重要维度。
维度列(Dimension): 用来标示数据行的各个类别信息。维度列的值都相同时,表明着一类的数据符合聚合操作。
指标列(Metric): 用来聚合和计算的列。这些指标列通常是一些数字,计算操作通常包括Count,Sum等。
与RDBMS做比较,DataSource可以理解为RDBMS中的表。

2.Segment结构

DataSource是一个逻辑概念,Segment是数据的实际物理存储格式。Druid通过Segment实现对数据的横纵向切割操作。Druid将不同时间范围内的数据存储在不同的Segment数据块中(横向切割),同时Segment也面向列进行数据压缩存储(纵向切割)。

集群架构

一、角色与依赖

角色

1. Realtime-node (实时节点)
主要负责即时摄入实时数据,以及生成Segemnt数据文件。
2. Historical-node (历史节点)
负责加载已经生成好的数据文件以提供数据查询。
3. Coordinator-node (协调节点)
负责历史节点的数据负载均衡,以及通过规则管理数据的生命周期。
4. Broker-node (查询节点)
对外提供数据查询服务,并同时从实时节点与历史节点查询数据,合并后返回给调用方。
**5. Indexing-servive (索引服务) **
出从(Master-Salave)结构的一组组件;Overload(**节点)为主节点,Middle-manager(中间件管理者)为从节点,Peon(苦工)。也能生成Segment数据文件。

外部依赖

1. Ingestion输入源
常用到的为Kafka,rabbitmq, twitter数据等。
2. Zookeeper集群状态管理服务
负责协调各个角色之间的任务启动停止等。
3. Metdata-storage – 元数据库
负责保存segment的源信息以及config,rules等信息。
4. Deep-storage – 数据文件存储服务
持久存储,负责保存segment数据,常用的是HDFS, Amazon S3等分布式存储。

集群组成

集群的管理层级

节点故障

历史节点
该节点就不会服务这个节点上的Segments。但是只要这些Segments仍然存在于DeepStorage,其他节点就会下载它们并服务这些Segments。
可以从集群中移除所有的历史节点,并且重新发布它们,也不会有任何的数据损失(因为数据最终都保存到DeepStorage中)。
DeepStorage
历史节点上已经加载了DeepStorage的Segments,仍然可用于查询。但是新进来的数据无法进入到集群中(DS挂掉)。
协调节点挂掉
数据的拓扑(data topology)停止服务,就不会有新的数据以及数据的负载均衡。因为协调节点会通知历史节点下载新数据。如果实时节点将Segment转存到DeepStorage,而没有历史节点去下载这些数据,会导致实时节点最终会丢弃这份过期的数据。
Broker
还会有其他的Broker接管请求,但是要至少保证有多余的Broker。
实时节点
根据发送流的语义,可以有多个实时节点或者tranquility同时运行,处理同一个输入流,每个实时节点分担输入流的一部分数据.
元数据存储
协调节点就无法找到集群中新的Segments(因为新的Segment一定会写入记录到元数据存储中)。但仍然可以提供当前集群的数据视图.
ZooKeeper
数据拓扑不会被更新(同协调节点挂掉),但是Broker仍然可以维护最近的数据拓扑,并继续提供查询的服务。

HTTP1.0,HTTP1.1,HTTPS和HTTP2.0的区别

HTTP1.0和HTTP1.1的一些区别

  1. 缓存处理,在HTTP1.0中主要使用header里的If-Modified-Since,Expires来做为缓存判断的标准,HTTP1.1则引入了更多的缓存控制策略例如Entity tag,If-Unmodified-Since, If-Match, If-None-Match等更多可供选择的缓存头来控制缓存策略。

  2. 带宽优化及网络连接的使用,HTTP1.0中,存在一些浪费带宽的现象,例如客户端只是需要某个对象的一部分,而服务器却将整个对象送过来了,并且不支持断点续传功能,HTTP1.1则在请求头引入了range头域,它允许只请求资源的某个部分,即返回码是206(Partial Content),这样就方便了开发者自由的选择以便于充分利用带宽和连接。
    错误通知的管理,在HTTP1.1中新增了24个错误状态响应码,如409(Conflict)表示请求的资源与资源的当前状态发生冲突;410(Gone)表示服务器上的某个资源被永久性的删除。

  3. Host头处理,在HTTP1.0中认为每台服务器都绑定一个唯一的IP地址,因此,请求消息中的URL并没有传递主机名(hostname)。但随着虚拟主机技术的发展,在一台物理服务器上可以存在多个虚拟主机(Multi-homed Web Servers),并且它们共享一个IP地址。HTTP1.1的请求消息和响应消息都应支持Host头域,且请求消息中如果没有Host头域会报告一个错误(400 Bad Request)。

  4. 长连接,HTTP 1.1支持长连接(PersistentConnection)和请求的流水线(Pipelining)处理,在一个TCP连接上可以传送多个HTTP请求和响应,减少了建立和关闭连接的消耗和延迟,在HTTP1.1中默认开启Connection: keep-alive,一定程度上弥补了HTTP1.0每次请求都要创建连接的缺点。

HTTP1.0和1.1现存的一些问题

  1. HTTP1.x在传输数据时,每次都需要重新建立连接,无疑增加了大量的延迟时间,特别是在移动端更为突出。

  2. HTTP1.x在传输数据时,所有传输的内容都是明文,客户端和服务器端都无法验证对方的身份,这在一定程度上无法保证数据的安全性。

  3. HTTP1.x在使用时,header里携带的内容过大,在一定程度上增加了传输的成本,并且每次请求header基本不怎么变化,尤其在移动端增加用户流量。

  4. 虽然HTTP1.x支持了keep-alive,来弥补多次创建连接产生的延迟,但是keep-alive使用多了同样会给服务端带来大量的性能压力,并且对于单个文件被不断请求的服务(例如图片存放网站),keep-alive可能会极大的影响性能,因为它在文件被请求之后还保持了不必要的连接很长时间。

HTTPS与HTTP的一些区别

  1. HTTPS协议需要到CA申请证书,一般免费证书很少,需要交费。

  2. HTTP协议运行在TCP之上,所有传输的内容都是明文,HTTPS运行在SSL/TLS之上,SSL/TLS运行在TCP之上,所有 传输的内容都经过加密的。

  3. HTTP和HTTPS使用的是完全不同的连接方式,用的端口也不一样,前者是80,后者是443。

  4. HTTPS可以有效的防止运营商劫持,解决了防劫持的一个大问题。

HTTP2.0的新特性

  1. 新的二进制格式(Binary Format),HTTP1.x的解析是基于文本。基于文本协议的格式解析存在天然缺陷,文本的表现形式有多样性,要做到健壮性考虑的场景必然很多,二进制则不同,只认0和1的组合。基于这种考虑HTTP2.0的协议解析决定采用二进制格式,实现方便且健壮。

  2. 多路复用(MultiPlexing),即连接共享,即每一个request都是是用作连接共享机制的。一个request对应一个id,这样一个连接上可以有多个request,每个连接的request可以随机的混杂在一起,接收方可以根据request的 id将request再归属到各自不同的服务端请求里面。

  3. header压缩,如上文中所言,对前面提到过HTTP1.x的header带有大量信息,而且每次都要重复发送,HTTP2.0使用encoder来减少需要传输的header大小,通讯双方各自cache一份header fields表,既避免了重复header的传输,又减小了需要传输的大小。

  4. 服务端推送(server push),HTTP2.0具有server push功能。

HTTP常见字段之 Content-Type

HTTP常见字段之 Content-Type

字段含义

指http发送信息至服务器时的内容编码类型。就是该请求的里面的信息是图片还是html文件啥的,用于告诉服务器和浏览器怎么解析该请求重的数据。本文主要介绍该字段与在ajax请求中常用的三个值:
application/x-www-form-urlencoded, multipart/form-data, application/json

application/x-www-form-urlencoded

Content-Type:application/json
name=ming&sex=male

FormData对象没有像JSON.stringify那样的方法能批量将对象形式转换为对应的形式

let userObj = {userName: ’xxx', age: '21'}
 formData.append('user', userObj)
 
------WebKitFormBoundaryyb1zYhTI38xpQxBK
Content-Disposition: form-data; name="user"

[object Object]

如需正常转换需手动实现转换函数或者借助qs库

var obj = {
    a: '2', 
    b: {c: 'test'}, 
    c: [ 
        {id: 1, name: 'xx'}, 
        {id:2 ,name: 'yy', info: {d: 4} }
    ]
}



a: 2
b[c]: test
c[][id]: 1
c[][name]: xx
c[][id]: 2
c[][name]: yy
c[][info][d]:4

multipart/form-data

请求体被分割成多部分,每部分使用 --boundary分割;

...
Content-Type: multipart/form-data; boundary=${boundary} 

--${boundary}
...
...

--${boundary}--

json

Content-Type: application/x-www-form-urlencoded
{"name": "ming", "sex":"male"}

对于一些复制的数据对象,对象里面再嵌套数组的话,建议使用application/json。json的形式的优点是它可以传递结构复杂的数据形式,但是json不支持二进制数据,必须转义二进制数据。

浏览器存储(sessionStorage, localStorage, cookie)

sessionStorage

作用域: 限定在文档源(document origin)级别;此外还限定在窗口中,即同源文档在不同的浏览器标签页中无法共享数据(*如果一个浏览器包含两个<iframe>元素,它们包含的文档是同源的,那么两者可以共享数据)。

有效期: 当该网页的标签页被关闭,那么所有通过seesionStorage存储的数据都会被删除。

localStorage

作用域: 限定在文档源(document origin)级别,也受浏览器供应商的限制,无法跨浏览器读写数据。

有效期: 存储的数据是永久性的,除非Web应用可以删除存储的数据,否则数据将一直存储在用户的电脑上,永不过期。

cookie

cookie数据会自动跟随http请求在web浏览器和web服务器之间传输。

作用域: 默认是限定在文档源(document origin)级别。并且默认与创建它的页面有关,并对该web页面以及和gaiweb页面同目录或者子目录的其他web页面可见,如http://www.a.com/b/index.html创建一个cookie,那么该cookie对页面http://www.a.com/b/other.htmlhttp://www.a.com/b/c/index.html可见,但对http://www.a.com/a/index.html不可见。但可以通过设置cookie的domain属性(cookie的域只能设置为当前的服务器的域)和path属性来改变。

有效期: 默认保存到浏览器关闭为止(*非标签页关闭),可以通过max-age属性来明确告诉浏览器cookie的有效期。

保存cookie:

function setcookie(name, vlaue, liveTime){
    var cookie = name+'='+encodeURIComponent(value);
    if(typeof liveTime === 'number'){
        cookie += ";max-age="+liveTime;
    }
    document.cookie = cookie;
}

如果要设置cookie的path和domain属性,只需以添加max-age属性相同的形式追加在cookie值后面即可。
如果需删除一个cookie,给该cookie值赋空值,并将max-age设置为0即可。

ReactNative踩坑之旅

环境

操作系统:MacOS Sierra(10.12.3)
react-native-cli版本:0.2.0
react-native版本:0.42.0


Image组件无法显示http请求的图片

reactNative默认是把http给禁用了,在Info.plist里面修改下设置就好了
App Transport Security Settings中添加Allow Arbitrary Loads属性并把属性设为YES
2017-03-05 11 01 25

引用react-native-vector-icons组件失败

var Icon = require('react-native-vector-icons/Ionicons');改为import Icon from 'react-native-vector-icons/Ionicons';即可,即用ES6的写法加载依赖。

[译] 浏览器内部揭秘(1)

原文连接: Inside look at modern web browser (part 1)

CPU,GPU,內存和多进程架构

本博客系列中的4篇文章中,我们将介绍Chrome浏览器从架构到渲染的具体细节。如果你想知道浏览器如何将你的代码转换为网站,你不清楚为那些可以提高性能的奇门技巧的原理,那么本系列适合你。
在本系列的第1部分,我们将介绍核心计算机术语和Chrome的多进程架构

注意:如果你熟悉CPU / GPU和进程/线程的概念,则可以跳到浏览器体系结构。

计算机的核心:CPU和GPU

为了更好地理解浏览器运行环境,我们需要了解一些计算机部件及其功能。

CPU(Central Processing Unit )

CPU可以被认为是计算机的大脑。CPU核心可以理解为办公室工作人员,他们可以逐个处理各式各样的任务。在过去大多数CPU都是单芯片。现在CPU通常是多核的,从而为你的手机和电脑拥有更强的计算能力。

CPU
图1:4个CPU核心作为办公室中的工作人员坐在各自的办公桌上处理任务

GPU(Graphics Processing Unit)

GPU最初是为处理图形而开发的。这就是为什么在图形环境中“using GPU”或“GPU backed”是与快速渲染和平滑交互相挂钩的。与CPU不同,GPU擅长处理简单任务,但同时跨多个核心。近年来,随着GPU发展,越来越多的计算任务在GPU上就可以完成。

CPU
图2很多只拿着扳手的GPU核心表明它们只可以处理有限的任务

当你在计算机或手机上启动应用程序时,CPU和GPU就是为应用程序服务的。通常,应用程序是在操作系统上调用CPU和GPU的。

hw-os-app
图3:三层计算机体系结构。机器硬件位于底部,操作系统位于中间,应用程序位于顶部。

在进程和线程上运行程序

在深入浏览器架构之前还要掌握的个概念是进程(Process)和线程(Thread)。
进程:可以理解为应用程序的执行程序。
线程:包含与于进程中,是进程中的实际运作单位。

Process-thread
图4:进程是定界框,线程是框内游动的鱼

当你启动一个应用程序时,操作系将创建一个进程。该程序可能会创建线程来帮助它工作。操作系统为进程提供了“板块”内存,并且该应用程序的所有状态都保存在该专用内存中。当你关闭应用程序时,该进程跟内存都会被释放。

memory
图5:使用内存存储应用程序数据的过程图

浏览器架构

那么如何使用进程和线程构建Web浏览器呢?它可能是一个具有许多不同线程的进程,或者是通过少许线程进行IPC通信的多个进程。

browser-arch
图7:不同浏览器体系结构图
这里要注意的一点是关于如何构建Web浏览器没有标准规范。不同浏览器的架构以及实现方法可能是完全不相同的。

在本博客系列,我们将使用Chrome最新架构(如下图)。左上角的是浏览器进程,负责协调应用程序中的其他进程。左下角的是渲染进程,为每个标签提供了一个单独占用的进程。(后续可能会给每个站点提供独立的进程,包括iframe)

chrome-arch
图8:Chrome的多进程架构图。渲染进程下的图层表示Chrome为每个选项卡运行的渲染进程。

每个进程控制哪些模块?

下表介绍了Chrome中的每个进程及其控制的内容

进程 控制的内容
浏览器 控制“chrome”部分,包括地址栏,书签,后退和前进按钮。还处理Web浏览器的不可见特权部分,例如网络请求和文件访问
渲染 控制显示网站的选项卡内的内容。
插件 控制网站使用的插件,例如flash。
GPU 独立于其他进程处理GPU任务。它被分成不同的进程,因为GPU处理来自多个应用程序的请求并将它们绘制在同一表面中。

browserui
图9:浏览器UI中各个部分相对应的进程

还有更多的进程,如扩展流程和实用流程。如果您想查看Chrome中正在运行的进程数,请点击选项菜单图标。这将打开一个窗口,其中包含当前正在运行的进程列表以及它们使用的CPU /内存量。

Chrome多进程架构的优点

上文有提到过Chrome是使用多个渲染进程的。在最简单的情况下,你可以想象每个选项卡都有自己的渲染进程。假设你打开了3个选项卡,每个选项卡都有独立的渲染进程,如果一个选项卡没有响应,则可以关闭无响应的选项卡并不会影响其他选项卡的运行。但是如果所有选项卡都共用一个渲染进程,则当一个选项卡无响应时,其他选项卡也都挂掉。

tabs
图10:每个选项卡有独立渲染进程跟所有选项卡公用一个渲染进程的区别

另一个好处就是能保证安全性和沙盒。浏览器可以利用操作系统提供限制进程权限的功能对某些进程进行沙箱处理。例如,Chrome浏览器可以限制涉及用户输入进程(比如渲染进程)对任意文件访问。

每个进程有自己的私有内存空间,它们通常保存公共框架的副本(例如V8是Chrome的JavaScript引擎)。但同一进程内的线程是无法共享内存的,因此每个线程占用的内存都会有所增加。为了节省内存,Chrome限制了可以启动的进程数量。限制的额度因设备的内存和CPU功率而改变,当进程数量达到限制时,Chrome会在一个进程中运行不同选项卡中相同站点的代码。

节省更多内存 - Chrome中的服务化

Chrome正在将浏览器程序的每个部分作为一个服务来运行,从而可以轻松拆分为不同的进程中或者整合到一个进程中。
一般情况下,当机器性能充分时,chrome可能会将每个服务分成不同的进程,从而提供更高的稳定性,当机器性能紧缺时,Chrome会将服务整合到一个进程中,从而节省内存占用。

servicfication
图11:Chrome将不同的服务转移到多进程或单进程中

渲染进程 - 站点隔离

站点隔离是Chrome中最近推出的一个功能,该功能是为每个跨网站iframe提供单独的渲染进程。之前每个选项卡的里面的站点(a.com)是与跨站点iframe(b.com)共用一个渲染进程的。这使得可以绕过浏览器的同源策略进行安全攻击,使得在一个站点在未经同意的情况下访问其他站点的数据。站点隔离可以避免这些安全攻击,而进程隔离是实现站点隔离的最有效方法。

isolation
图12:站点隔离图

总结

在这篇文章中,我们了解了浏览器体系结构、多进程体系结构的优、Chrome中与多进程架构密切相关的服务化以及站点隔离。在下一篇文章中,我们将开始深入研究这些进程和线程之间发生的事情。

JS继承模式

前言

  面向对象的三大特征分别为抽象、继承、封装。JS并没有接口继承,主要依靠原型链来实现继承。

原型链继承

function Supertype(){
  this.property = true;
}
Supertype.prototype.getSuperValue = function(){
  return this.property;
}

function SubType(){
  this.subproperty = false;
}
// 继承Supertype
SubType.prototype = new Supertype();
SubType.prototype.getSubValue = function(){
  return this.subproperty;
}

var instance = new SubType();
console.log(instance.getSuperValue()); //true

缺点:引用类型值得原型属性会被所有实例共享,如下列代码所示

function SuperType(){
  this.colors = ["red","blue","green"];
}
function SubType(){
}
//继承SuperType
SubType.prototype = new SuperType();

var instance1 = new SubType();
instance1 .colors.push("black");
console.log(instance1.colors); //"red,blue,green,black"

var instance2 = new SubType();
console.log(instance2.colors); //"red,blue,green,black"

借用构造函数

function SuperType(){
  this.colors = ["red","blue","green"];
}
function SubType(){
  //继承SuperType
  SuperType.call(this);
}

var instance1 = new SubType();
instance1 .colors.push("black");
console.log(instance1.colors); //"red,blue,green,black"

var instance2 = new SubType();
console.log(instance2.colors); //"red,blue,green"

缺点: 函数无法复用


组合继承

function SuperType(name){
  this.name = name;
  this.colors = ["red","blue","green"];
}
SuperType.prototype.sayName = function(){
	console.log(this.name);
}
function SubType(name){
  //继承属性
  SuperType.call(this, name);
}
SubType.prototype = new SuperType();
SubType.prototype.constructor = SubType;


var instance1 = new SubType("yu");
instance1 .colors.push("black");
console.log(instance1.colors); //"red,blue,green,black"
instance1.sayName(); //"yu"

var instance2 = new SubType("ming");
console.log(instance2.colors); //"red,blue,green"
instance2.sayName(); //"ming"

优点: 组合继承避免了原型链和借用构造函数的缺陷,融合了它们的优点,成为JS中最常用的继承模式
缺点:需要手动将SubType原型里面的constructor属性指向SubType。

ES6:export default 和 export 区别

export default 和 export 区别:

1.export与export default均可用于导出常量、函数、文件、模块等
2.你可以在其它文件或模块中通过import+(常量 | 函数 | 文件 | 模块)名的方式,将其导入,以便能够对其进行使用
3.在一个文件或模块中,export、import可以有多个,export default仅有一个
4.通过export方式导出,在导入时要加{ },export default则不需要

/* 1.export  */
//demo1.js
export const str = 'hello world'
export function f(a){ return a+1}
对应的导入方式:

//demo2.js
import { str, f } from 'demo1' //也可以分开写两次,导入的时候带花括号


/*  2.export default */
//demo1.js
export default const str = 'hello world'
对应的导入方式:

//demo2.js
import str from 'demo1' //导入的时候没有花括号

使用export default命令,为模块指定默认输出,这样就不需要知道所要加载模块的变量名

//a.js
let sex = "boy";
export default sex(sex不能加大括号)
//原本直接export sex外部是无法识别的,加上default就可以了.但是一个文件内最多只能有一个export default。
// 其实此处相当于为sex变量值"boy"起了一个系统默认的变量名default,自然default只能有一个值,所以一个文件内不能有多个export default。
// b.js
// 本质上,a.js文件的export default输出一个叫做default的变量,然后系统允许你为它取任意名字。所以可以为import的模块起任何变量名,且不需要用大括号包含
import any from "./a.js"
import any12 from "./a.js" 
console.log(any,any12)   // boy,boy

转载自 简书-谢一咕

数据结构与算法--排序(JS实现)

前言

  复习数据结构的时候发现都是以JAVA为例,虽然JS的算法用的比较少,很多时候基本上也用不到。但还是趁有空折腾一下吧,主要实现内排序的算法。

排序分类

根据排序过程中借助的主要操作,我们将内排序分为:
插入排序类:直接插入排序,希尔排序
选择排序类:简单选择排序,堆排序
交换排序类:冒泡排序,快速排序
归并排序类:归并排序


直接插入排序

基本**

将一个记录插入到已经排好序的有序表中,从而得到一个新的,记录数增1的有序表

代码实现

function insertSort(data){
  var temp;
  for (var i = 1; i < data.length; i++) {
    temp = data[i];
    if(data[i] < data[i-1]){
      for (var j = i-1; data[j] > temp; j--) {
        data[j+1] = data[j];
      };
      data[j+1] = temp;
    }
  };
  return data;
}

希尔排序

基本**

将相距某个“增量”的记录组成一个子序列,这样才能保证在子序列内分别进行直接插入排序后得到的结果是基本序列而不是局部有序
(*基本系列:就是小的关键字基本在前面,大的基本在后面,不大不小的基本在中间)

代码实现

function shellSort(data){
  var increment = data.length;
  var temp;
  do{
    increment =  Math.floor(increment/3)+1;
    for (var i = increment; i < data.length; i++) {
      if (data[i] < data[i-increment]) {
        temp = data[i];
        for (var j = i-increment; temp<data[j]; j-=increment) {
          data[j+increment] = data[j];
        };
        data[j+increment] = temp;
      };
    };
    console.log(data);
  }
  while(increment>1);
  return data;
}

简单选择排序

基本**

通过n-1次关键字简的比较,从n-i+1个记录中选出关键字最小的记录,并和第i(i《i《n)个记录换之

代码实现

function selectSort(data){
  var min;
  for (var i = 0; i < data.length; i++) {
    min = i;
    for (var j = i+1; j < data.length; j++) {
      if (data[min] > data[j]) {
        min = j;
      };
    };  
    if ( i!= min) {
      swap(data,i,min);
    };
  };
  return data;
}

堆排序

基本**

将待排序的序列构造成一个大顶堆。此时,整个序列的最大值就是堆顶的根节点。将它移走,然后将剩余n-1个序列重新构造成一个堆,这样就会得到n个元素中的次大值。如此反复执行,便能得到一个有序序列了。

代码实现

function heapSort (data) {
  for (var i = Math.floor(data.length/2); i >= 0; i--) {
    data = heapAdjust(data, i, data.length-1)
  };
  for(var i = data.length-1;i>0;i--){
    swap(data, 0, i);
  
    data = heapAdjust(data, 0, i-1);
  }
  return data;
}
//构造大顶堆
function heapAdjust(data, s, m){
  var temp = data[s];
  for (var j = (2*s+1); j <= m; j=j*2+1){
    if (j<m && data[j]<data[j+1]) {
      ++j;
    };
    if (temp >= data[j]) {
      break;
    };
    data[s] = data[j];
    s = j;
  };
  data[s] = temp;
  return data;
}

冒泡排序

基本**

两两比较相邻记录的关键字,如果反序则交换

代码实现

function bubbleSort(data){
  var flag = true;
  for (var i = 0; i < data.length && flag; i++) {
    flag = false;
    for (var j = data.length; j >= i; j--) { //注意!!!j是从后往前
      if (data[j] <= data[i]) {
        swap(data,i,j);
        flag = true;
      };
    };
  };
  return data;
};

function swap(arr, i ,j){
  var temp = arr[i];
  arr[i] = arr[j];
  arr[j] = temp;
}

快速排序

基本**

通过一样排序将待排记录分割成独立的两部分,其中一部分记录的关键字均比另一部分的关键字小,则可分别对这两部分记录继续进行排序,以达到整个序列有序的目的

代码实现

function quickSort(data){
  return QSort(data,0,data.length-1);
}
function QSort(data, low, high){
  var pivot; //枢轴值
  if (low<high) {
    pivot = partition(data, low, high);

    QSort(data, low, pivot-1);
    QSort(data, pivot+1, high);
  };
  return data;
}
function partition(data, low, high){
  var pivotkey = data[low];
  while(low<high){
    while(low<high && data[high] >= pivotkey){
      high--;
    }
    swap(data,low,high);
    while(low<high && data[low]<=pivotkey){
      low++;
    }
    swap(data,low,high);
  }
  return low;
}

Recommend Projects

  • React photo React

    A declarative, efficient, and flexible JavaScript library for building user interfaces.

  • Vue.js photo Vue.js

    🖖 Vue.js is a progressive, incrementally-adoptable JavaScript framework for building UI on the web.

  • Typescript photo Typescript

    TypeScript is a superset of JavaScript that compiles to clean JavaScript output.

  • TensorFlow photo TensorFlow

    An Open Source Machine Learning Framework for Everyone

  • Django photo Django

    The Web framework for perfectionists with deadlines.

  • D3 photo D3

    Bring data to life with SVG, Canvas and HTML. 📊📈🎉

Recommend Topics

  • javascript

    JavaScript (JS) is a lightweight interpreted programming language with first-class functions.

  • web

    Some thing interesting about web. New door for the world.

  • server

    A server is a program made to process requests and deliver data to clients.

  • Machine learning

    Machine learning is a way of modeling and interpreting data that allows a piece of software to respond intelligently.

  • Game

    Some thing interesting about game, make everyone happy.

Recommend Org

  • Facebook photo Facebook

    We are working to build community through open source technology. NB: members must have two-factor auth.

  • Microsoft photo Microsoft

    Open source projects and samples from Microsoft.

  • Google photo Google

    Google ❤️ Open Source for everyone.

  • D3 photo D3

    Data-Driven Documents codes.