Zach Ke's Notes

Quick notes


  • 首页

  • 关于

  • 标签

  • 分类

  • 归档

  • 搜索

浅谈之-在浏览器中输入一个网址后发生了什么

发表于 2018-07-01 | 分类于 前端相关 , 前端浅谈系列 | | 阅读次数:

这个是一道非常经典的面试题,也是我在面试前端和后端经常会问的一个问题。因为这道题可以很大程度上考验一个开发者的技术深度和广度,而不仅仅限于平时日常工作中做的那些东西。
这道题严格上来说并没有标准答案,因为每一个环节都可以做非常深的延展。我这边也是参考一些网上的答案,然后配合自己的见解,给出一个我自己认为的一个比较全的答案。
主要分为以下几个环境:

  1. 浏览器解析该URL得到IP地址
  2. 浏览器根据解析得到的IP地址向服务器发送一个 HTTP 请求
  3. 服务器收到请求并进行处理,最后返回响应
  4. 浏览器对该响应进行解码,渲染显示
  5. 断开 TCP 连接,并将资源进行本地缓存
阅读全文 »

golang 踩坑之 - 服务的文件句柄超出系统限制(too many open files)

发表于 2018-06-26 | 分类于 golang相关 | | 阅读次数:

之前有发生一个情况。就是我们有两个go程序服务A和B,其中A服务会调用B服务的http接口,而B服务是一个对外的长链接服务。两个服务在同一台服务器,其中在A服务的log中,发现在调用B服务接口的时候,会报这个错误:

1
2
[Error] [/data/code/go/src/stream-forward/phone_conn_pool.go 80] [2018-06-24 21:38:29] 
[request phone(9a7b01445fd7ec85f122eadbdc07e084) create channel: Get https://xxx.airdroid.com:9088/create_channel?id=xxx&token=xxx&host=xx-bd.airdroid.com&port=9991: dial tcp xxx.xxx.xxx.xxx:9088: i/o timeout]

即请求B服务的接口出错了,而且这两个服务是在同一台服务器上的。后面直接在这一台机子上,试着curl 这个接口地址。发现也不行:
1
2
[kbz@ovm-orcobyj8 dataforwardsrv]$ curl 'https://xxx.airdroid.com:9088/create_channel?id=xxx&token=xxx&host=xxx-bd.airdroid.com&port=9991'
curl: (7) Failed connect to xxx.airdroid.com:9088; Connection timed out

阅读全文 »

golang 踩坑之 - https下开启http2会在Safari下报错(http2 stream closed)

发表于 2018-06-22 | 分类于 golang相关 | | 阅读次数:

之前项目的一个转发服务有发生过一个问题,就是在新版的Safari上(版本11),https 的链接会一直连不上。然后我看了一下log,发现一直在刷log,明显是Safari一直在重试请求,而且一直报这个错误:

1
[id(12a0de8483dc83df60d2d0ac49118e57): io copy fail : http2: stream closed

这个错误就是http2的错误,但是为啥就新版的Safari会,旧版的Safari和chrome 和 Firefox都正常??

阅读全文 »

golang 踩坑之 - slice bounds out of range

发表于 2018-06-22 | 分类于 golang相关 | | 阅读次数:

之前有发生过一个现象,我们的一个go服务定时会出现重启的行为,时间间隔有可能是几个小时,也有可能是几天。 后面查看了一下supervisor的error log,发现:

1
2
3
4
5
6
7
8
9
panic: runtime error: slice bounds out of range

goroutine 7217 [running]:
panic(0x6f6a40, 0xc42000c0a0)
/usr/local/go1.7.6/src/runtime/panic.go:500 +0x1a1
main.phoneHandler(0x8b3ba0, 0xc4200ee088)
/data/code/go/src/stream-forward/forward_handlers.go:27 +0x902
created by main.phoneServe
/data/code/go/src/stream-forward/main.go:72 +0xeb

看情况好像是一个 切片数组越界的错误?? 我们定位到具体的代码:

1
2
3
4
buf := make([]byte, 512)

n := bytes.Index(buf, []byte{'\n'})
deviceId := string(buf[:n])

果然发现了一个 可能会导致slice切片越界的行为。如果 index 检索不到对应的字符,那么n就会为 -1,当 n为-1 的时候,就会报这个错误。 所以这边要改成:
1
2
3
4
5
6
n := bytes.Index(buf, []byte{'\n'})
// 这边如果返回-1的话,那么下面那个slice就会报一个数组越界的错误,导致程序退出
if n <= 0 {
return
}
deviceId := string(buf[:n])

这边只要提前判断就行了。

前端工具集(11) -- 实现短信输入区分多条

发表于 2018-06-21 | 分类于 前端工具集 | | 阅读次数:

之前做过一个项目(web.airdroid.com的短信模块)是可以在web端的输入框输入短信内容,然后调用手机端的API来发送短信。这时候就需要做到跟手机端的短信app的一样的提示效果,即用户在输入的时候,要提示当前是否会拆分多条短信,还有就是当前这条短信的剩余输入字数。最后上线的部分效果图如下:
1
在实现之前,这边先科普以下,一条短信会有几个字符可以输入,还有就是什么情况下会需要拆分多条短信??
上世纪80年代无线传输的带宽不高,这就要求手机短信要言简意赅。短信发明人Hillebrand为遵从这一要求,经过试验后将160个字符作为短信长度上限,英文字母可发160个(参考文献)。
因为英文字母采用7位ASCII编码,而汉字则采用8位UCS-2编码并占2个字节,所以160个字符按照7位ASCII编码来换算,即160X7=1120位;而汉字是按照8位的UCS-2编码,即8位一个字符,一个汉字占2个字符,这样1120位换算成汉字数就是1120/8/2=70。如果换算成字节(byte)的话,那么一条短信就是 1120/8 = 140 个字节(一个字节8位(bit))
也就是说,如果是单条短信的话,如果只输入英文字母的话,那么可以输入160个字符,如果输入汉字的话,可以输入70个字符,如果是中英混输的话,就按照汉字来算(只要内容里面有一个汉字,那么整个内容的编码就全部按照汉字的编码来算)。
也就是说,当英文字母超过160个字符之后,这时候短信就会拆分成两条。 如果是汉字超过70个字符之后,也会拆成两条。

阅读全文 »

zoom 和 transform:scale的差别

发表于 2018-06-19 | 分类于 前端相关 | | 阅读次数:

之前在做 web.airdroid.com 截屏模块的时候, 有遇到一个问题。就是如果截屏全屏的时候,如果有些机子的屏幕图片的高度比浏览器当前的高度还大,就会出现左下角的AirDroid LOGO 消失不见。
截图如下:
1

阅读全文 »

使用input=file 上传的时候,选择同样的图片,第二次不会再触发onChange事件

发表于 2018-06-19 | 分类于 前端相关 | | 阅读次数:

之前在做一个项目的时候,有用到 input=file 上传, 并监听onchange事件。也就是当选择的文件有变化的时候,就会触发change事件。但是有一种,就是第二次选择的图片和第一次的图片一样。这时候,发现第二次选择之后,就不会再触发change事件了。
解决方法就是每次上传之后, 把这个 input 的 value 清空, 即 event.target.value = ‘’;但是这种方法在ie10下会有问题。所以更好的方法就是在input上面套一层form,然后使用 form.reset() 方法来清除。
比如这样:

阅读全文 »

前端工具集(10) -- 用js实现浏览器全屏 fullscreen

发表于 2018-06-15 | 分类于 前端工具集 | | 阅读次数:

因为前段有做了一个功能是关于全屏显示图片和视频,因此这边稍微整理了一些关于在浏览器显示全屏的一些API。
HTML 5中的full screen 就是用来做全屏API的。不过还是会有一些浏览器兼容性问题。
1
可以看到IE下只有IE11才支持。而且其他支持的主流浏览器,也大部分都要使用前缀才行。主要有以下几个API:

阅读全文 »

前端工具集(9) -- 正则匹配文本中的链接并转化为A标签

发表于 2018-06-15 | 分类于 前端工具集 | | 阅读次数:

前段时间在做pc内嵌页的时候,有遇到过一个需求,就是要把用户聊天记录中的链接匹配出来,并转化为A标签,这个就涉及到链接的正则匹配了。刚开始试着找了一下网上的正则匹配表达式,后面发现还是不全。
后面只好自己写了一个方法,总算可以满足大部分的情况,不过还是有一点不足的是,就是还是不能匹配ip地址的链接,刚开始有试着兼容了一下这个模式,后面发现要兼容这个东西的坑太多了,就算能兼容少部分的情况,但是很多情况下还是会有bug,再加上平时ip地址的链接还是比较少的,因此就先不兼容了。代码如下:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
function Linkify = function (text, opts) {
var target, href;
opts = opts || {};
target = opts.target || '_blank';
// 这个正则不匹配 ip 地址, 比如 http://192.168.40.124:8090/issues/?filter=11603
// be 后缀因为 youtube 短链接是 be 后缀的,会比较常用。如: https://youtu.be/uFngFoR_3KE https://321.show/rAN0Q5M5wp6
var urlReg = /((http|https|ftp)\:\/\/)?([a-zA-Z0-9]([a-zA-Z0-9\-]{0,61}[a-zA-Z0-9])?\.)+(com|me|io|org|net|de|uk|fr|us|cn|hk|tw|gl|be|show|au)(([:\/?])([\w\-\.,@?^=%&amp;:/~\+#*]+[\w\-\@?^=%&amp;/~\+#]{0,1}))?/g;
var originText = text;
var encryObj =[];
text = text.replace(urlReg, function (match) {
if(originText.substr(arguments[arguments.length-2]-1,1) == "@"){
// 如果是邮箱,就不管
return match;
}
if (match.indexOf('http') > -1) {
// http/https 协议开头
href = match;
} else {
// 没有协议
href = 'http://' + match;
}
// 使用约定的一个特殊字符来代替
encryObj.push('<a class="linkable" href="' + href + '" target="' + target + '">' + match + '</a>');
return ("$=A=+ (encryObj.length - 1) +=A=$");
});
// 设置html代码格式
text = text.replace(/\n/g, '<br>');
// 这里不能转义,不然多字符的时候,会折行
//text = text.replace(/\s/g, '&nbsp;');
// 最后再转回来
for (var i = 0; i < encryObj.length; i++){
text = text.replace(new RegExp("\\$=A=\\{\\{" + i + "\\}\\}=A=\\$", "g"), encryObj[i]);
}
return text;
};

调用的话:

1
2
3
4
var text = '我的网站 www.sample.com.欢迎光临。';
console.log(Linkify(text));
最后得到:
我的网站 <a class="linkable" href="http://www.sample.com" target="_blank">www.sample.com</a>.欢迎光临。

前端工具集(8) -- 兼容IE的脚本加载器

发表于 2018-06-15 | 分类于 前端工具集 | | 阅读次数:

前段时间在做pc内嵌页的时候,有遇到过异步加载语言文件,并且因为有兼容到XP系统,即IE6内核。所以就写了一个兼容IE6文档模式打开的脚本加载器。

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
/**
* 脚本加载器 (兼容ie6,兼容文档系统打开方式)
*/
function LoadScript (url,successCb){
var header = document.getElementsByTagName("head")[0];
var loader = document.createElement('script');
// 成功事件
var successed = function(){
successCb && successCb();
};
if (loader.readyState) { //IE
loader.onreadystatechange = function(){
if (loader.readyState == "loaded" || loader.readyState == "complete") {
loader.onreadystatechange = null;
successed();
}
}
} else { //Others
loader.onload = function(){
successed();
};
}
// 加载语言文件
loader.src = url;
header.appendChild(loader);
};

调用的话:

1
2
3
4
var path = baseUrl + "lang/en.js";
LoadScript(path, function(){
console.log("load lang success");
});

ie8,ie9 使用 XDomainRequest 进行跨域

发表于 2018-06-14 | 分类于 前端相关 | | 阅读次数:

之前有写过一篇关于ajax的封装库:前端工具集(7) -- 原生js实现并扩展jquery的ajax功能 里面有提到如果是ie10以下的ajax请求,都是用ActiveXObject这个对象来进行异步请求的。而且只能进行同域下的异步请求。

ActiveXObject对象

ActiveXObject 这个对象是 ie5 才加进去的,也就是如果要在 ie5 及以上(ie5, ie6, ie7, ie8, ie9)要执行同域下的异步请求的话, 那么就用这个。

阅读全文 »

关于 XMLHttpRequest 对象需要注意的地方

发表于 2018-06-11 | 分类于 前端相关 | | 阅读次数:

这段时间重新理了一下ajax技术,并重新理了一下XMLHttpRequest 对象,发现还是有几个地方比较容易忘记或者是需要注意的几个地方。

Ajax和XMLHttpRequest不是同一个东西

Ajax不等同于XMLHttpRequest,细究起来它们两个是属于不同维度的2个概念。
ajax是一种技术方案。它依赖的是现有的CSS/HTML/Javascript,而其中最核心的依赖是浏览器提供的XMLHttpRequest对象,是这个对象使得浏览器可以发出HTTP请求与接收HTTP响应。

AJAX stands for Asynchronous JavaScript and XML. AJAX is a new technique for creating better, faster, and more interactive web applications with the help of XML, HTML, CSS, and Java Script.

What is AJAX?www.tutorialspoint.com/ajax/what_is_ajax.htm

用一句话来总结两者的关系:我们使用XMLHttpRequest对象来发送一个Ajax请求。

阅读全文 »

使用 git cherry-pick 来合并某一个分支

发表于 2018-06-11 | 分类于 git 操作 | | 阅读次数:

之前在做一个项目的4.0改版的时候,从项目中的dev分支拉了一个分支4.x作为新版4.x的分支,然后在这 4.x 分支做了很多修改,包括很多图片替换,修改了很多bug。其中发现有些bug的fix,其实也需要合并到dev去。这时候就麻烦了,因为不能直接把4.x的内容直接merge 到 dev 分支。因为会把之前4.x分支的很多修改都合并进去。这不是我们想要的,我们想要的只是要把当前4.x分支的这个bug fix 的commit 提交合并到 dev 分支,而其他的commit不用。这时候就要用 git 的 cherry-pick 来处理。
举个例子: 比如我们在 4.x 的分支上,对Base.js 进行了修改。

阅读全文 »

前端工具集(7) -- 原生js实现并扩展jquery的ajax功能

发表于 2018-06-10 | 分类于 前端工具集 | | 阅读次数:

之前在做手机端页面的时候,为了减少体积,舍弃了jquery和zepto, 自己用原生写了一个ajax库,不仅可以实现jquery库的ajax功能,而且还进行了扩展,主要有以下功能:

  1. 支持ajax跨域请求
  2. 支持jsonp跨域请求
  3. 支持异步加载js文件
  4. 支持deferred用法或者直接传入回调参数的用法
  5. 支持同步调用
  6. 支持ajax请求失败的加载重试次数设置
  7. 兼容ie6-ie9 的异步同域请求,因为有兼容 window.ActiveXObject 对象

不支持的功能:

  1. xhr对象的上传和下载,这个是库没有,因为做这个库的初衷就是更好的加载js资源或者进行接口请求操作。 如果是要专门针对ajax上传和下载文件的,那么应该要重新封装一个库。
  2. 不支持ie8,ie9的跨域请求,因为没有封装XDomainRequest对象,可以参考这一篇: ie8,ie9 使用 XDomainRequest 进行跨域,至于ie8以下的异步跨域请求,那就不能用ajax的方式了,得用其他的方式,比如如果是get的话,那么就可以用jsonp来处理,可以参照这个:前端工具集(1) -- jsonp原生实现
  3. ie 10 开始支持xhr对象,不过没有withCredentials这个属性,所以如果是ie10的话,并且需要支持cookie跨域的话,那么就需要将cookie的内容读取出来,然后放到参数里面,最后由服务端来进行读取。

具体代码如下:

阅读全文 »

IE 6, IE 7 调试神器 firebug lite

发表于 2018-06-10 | 分类于 前端相关 | | 阅读次数:

之前在做一个pc端内嵌页项目的时候,因为要兼容XP系统,而XP系统的webview内核是 ie6,所以在调试IE 6, IE 7 的时候,发现调试非常难调,尤其是webview调试,根本没有所谓的调试窗口,后面发现有一个神器,就是firebug lite版,可以让你轻松的调试ie。
其实就是在html标签后面嵌入一段js:

1
2
3
4
5
6
7
8
9
10
11
12
13
<script type="text/javascript">
javascript:(function(F,i,r,e,b,u,g,L,I,T,E){
if(F.getElementById(b))return;
E=F[i+'NS']&&F.documentElement.namespaceURI;
E=E?F[i+'NS'](E,'script'):F[i]('script');
E[r]('id',b);
E[r]('src',I+g+T);
E[r](b,u);
(F[e]('head')[0]||F[e]('body')[0]).appendChild(E);
E=new Image;
E[r]('src',I+L);
})(document,'createElement','setAttribute','getElementsByTagName','FirebugLite','4','firebug-lite.js','releases/lite/latest/skin/xp/sprite.png','https://getfirebug.com/','#startOpened');
</script>

只要放在 html 闭合标签的后面,让其加载,然后就可以出现调试窗口框了

阅读全文 »

nginx 配置gzip以优化站点资源加载速度

发表于 2018-06-10 | 分类于 nginx相关 | | 阅读次数:

将官网的一些静态资源,比如 js ,css, 图片 设置成 gzip 压缩的方式, 可以提高静态资源的加载速度
因为我们用的是nginx,所以可以通过nginx来配置,直接在nginx.conf添加一下代码:

1
2
3
4
5
6
7
8
9
10
# Gzip Settings
gzip on;
gzip_disable "msie6";
gzip_vary on;
gzip_proxied any;
gzip_min_length 1000;
gzip_comp_level 4;
gzip_buffers 16 8k;
gzip_http_version 1.1;
gzip_types text/plain text/css application/json application/javascript application/x-javascript text/xml application/xml application/xml+rss text/javascript image/svg+xml;

实现效果的截图如下:

阅读全文 »

pc内嵌页取消IE "已限制此网页运行可以访问计算机的脚本" 的提示

发表于 2018-06-10 | 分类于 前端相关 | | 阅读次数:

之前有个项目是给pc端的桌面应用做内嵌页,也就是说这个项目的页面不是线上的页面,而是打包在pc端的安装包里面,而且pc端还没有开webserver来显示页面,而是直接用文档模式来打开html页面,后面有发生一种情况就是如果直接用文档模式打开html页面,并且有引入js脚本的话,会出现这种提示:
1

阅读全文 »

前端工具集(6) -- 上传的时候判断所选文件是否为文件夹

发表于 2018-06-09 | 分类于 前端工具集 | | 阅读次数:

之前做项目,有做到一个就是上传的功能,其中Chrome和Firefox支持文件夹上传的,但是Safari还不支持文件夹上传,因此需要去判断当前用户选择上传的文件是不是一个文件夹,如果是文件夹的话,那么就不让他上传,因此才有这个方法。
代码如下:

阅读全文 »

前端工具集(5) -- 文件拖入禁止浏览器响应打开

发表于 2018-06-09 | 分类于 前端工具集 | | 阅读次数:

之前项目中有出现一种情况,就是项目的网页上,有拖拽上传的操作,但是有时候用户drop的地方如果放错,比如我拖拽一张图片,然后放到页面放错了,不是放到指定的drop容器里面,而是其他元素,这时候浏览器就会将这张图片显示出来,以文档模式打开,并覆盖当前页面,这种体验是很糟糕的。因此我们需要禁止掉浏览器的这种默认行为。
具体代码如下:

阅读全文 »

前端工具集(4) -- 禁止backspace后退页面

发表于 2018-06-09 | 分类于 前端工具集 | | 阅读次数:

之前有在项目中遇到按下Backspace键让浏览器后退的问题, 主要逻辑就是当敲Backspace键时,事件源类型为密码或单行、多行文本的,或者是可编辑DIV,并且readonly属性不为true和enabled属性不为false的,则退格键生效,其他情况都失效。
网上其实有很多解决方法,但是或多或少都不够全面,后面自己修改了以下,用的这个版本会比较全面一点:

阅读全文 »
1…13141516
Zach Ke

Zach Ke

做最咸的那一条

316 日志
31 分类
83 标签
GitHub
© 2024 Zach Ke
由 Hexo 强力驱动
|
主题 — NexT.Pisces v5.1.4