Skip to content

Commit db8a054

Browse files
committed
25/07/11
1 parent 94be065 commit db8a054

17 files changed

Lines changed: 274 additions & 253 deletions

‎Environment/建立DNS隧道绕过校园网认证.md‎

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -115,7 +115,7 @@ Debug queue.c:300 Flushing outgoing data
115115
```
116116
要注意的是无论是本地的终端还是服务器的终端都需要保持其运行才能继续正常使用,毕竟如果终端掉了进程结束了也就不存在封包解包的操作了,另外实际使用速度还是比较感人的,毕竟其有大量的封包拆包操作。
117117

118-
## 最后
118+
## 总结
119119
最终还是没能成功实现想要的功能,最后使用`dnslog`探查了一下实际上是有`dns`查询的,还是需要研究一下究竟是什么阻拦策略导致没有完成隧道的建立。想来三级域名的`A`记录其实是可以携带一点信息的,即`abc.example.com`可以携带`abc`这个信息过去。此外还有一个终极大招,直接物理方案解决,毕竟`AP`可是在宿舍里边的。
120120

121121

‎JavaScript/JavaScript异步机制.md‎

Lines changed: 47 additions & 35 deletions
Original file line numberDiff line numberDiff line change
@@ -13,41 +13,48 @@ while(--i) { console.log(i); }
1313
console.log("while 执行完毕我才能执行");
1414
```
1515
### 异步
16-
异步执行就是非阻塞模式执行,每一个任务有一个或多个回调函数`callback`,前一个任务结束后,不是执行后一个任务,而是执行回调函数,后一个任务则是不等前一个任务结束就执行,所以程序的执行顺序与任务的排列顺序是不一致的、异步的。浏览器对于每个`Tab`只分配了一个`Js`线程,主要任务是与用户交互以及操作`DOM`等,而这也就决定它只能为单线程,否则会带来很复杂的同步问题,例如假定`JavaScript`同时有两个线程,一个线程在某个`DOM`节点上添加内容,另一个线程删除了这个节点,这时浏览器无法确定以哪个线程的操作为准。
16+
异步执行就是非阻塞模式执行,每一个任务有一个或多个回调函数`callback`,前一个任务结束后,不是执行后一个任务,而是执行回调函数,后一个任务则是不等前一个任务结束就执行,所以程序的执行顺序与任务的排列顺序是不一致的、异步的。浏览器对于每个`Tab`只分配了一个`Js`线程,主要任务是与用户交互以及操作`DOM`等,而这也就决定它只能为单线程,否则会带来很复杂的同步问题。例如假定`JavaScript`同时有两个线程,一个线程在某个`DOM`节点上添加内容,另一个线程删除了这个节点,这时浏览器无法确定以哪个线程的操作为准。
17+
18+
在下面的示例中需要注意的是,`W3C`在`HTML`标准中规定,规定要求`setTimeout`中低于`4ms`的时间间隔算为`4ms`。此外,这与浏览器设定、主线程以及任务队列也有关系,执行时间可能大于`4ms`,例如老版本的浏览器都将最短间隔设为`10`毫秒。对于那些`DOM`的变动尤其是涉及页面重新渲染的部分,通常不会立即执行,而是每`16`毫秒执行一次,这时使用`requestAnimationFrame()`的效果要好于`setTimeout()`。
1719

1820
```javascript
1921
setTimeout(() => console.log("我后执行"), 0);
20-
// 注意:W3C在HTML标准中规定,规定要求setTimeout中低于4ms的时间间隔算为4ms,此外这与浏览器设定、主线程以及任务队列也有关系,执行时间可能大于4ms,例如老版本的浏览器都将最短间隔设为10毫秒。另外,对于那些DOM的变动尤其是涉及页面重新渲染的部分,通常不会立即执行,而是每16毫秒执行一次。这时使用requestAnimationFrame()的效果要好于setTimeout()。
2122
console.log("我先执行");
2223
```
2324

2425
## 异步机制
25-
首先来看一个例子,与上文一样来测试一个异步执行的操作
26+
首先来看一个例子,与上文一样来测试一个异步执行的操作。
27+
2628
```javascript
2729
setTimeout(() => console.log("我在很长时间之后才执行"), 0);
2830
var i = 3000000000;
2931
while(--i) { }
3032
console.log("循环执行完毕");
3133
```
32-
本地测试,设置的`setTimeout`回调函数大约在`30s`之后才执行,远远大于`4ms`,我在主线程设置了一个非常大的循环来阻塞`Js`主线程,注意我并没有设置一个死循环,假如我在此处设置死循环来阻塞主线程,那么设置的`setTimeout`回调函数将永远不会执行,此外由于渲染线程与`JS`引擎线程是互斥的,`Js`线程在处理任务时渲染线程会被挂起,整个页面都将被阻塞,无法刷新甚至无法关闭,只能通过使用任务管理器结束`Tab`进程的方式关闭页面。
34+
35+
本地测试,设置的`setTimeout`回调函数大约在`30s`之后才执行,远远大于`4ms`,我在主线程设置了一个非常大的循环来阻塞`Js`主线程,注意我并没有设置一个死循环,假如我在此处设置死循环来阻塞主线程,那么设置的`setTimeout`回调函数将永远不会执行。此外由于渲染线程与`JS`引擎线程是互斥的,`Js`线程在处理任务时渲染线程会被挂起,整个页面都将被阻塞,无法刷新甚至无法关闭,只能通过使用任务管理器结束`Tab`进程的方式关闭页面。
36+
3337
`Js`实现异步是通过一个执行栈与一个任务队列来完成异步操作的,所有同步任务都是在主线程上执行的,形成执行栈,任务队列中存放各种事件回调(也可以称作消息),当执行栈中的任务处理完成后,主线程就开始读取任务队列中的任务并执行,不断往复循环。
34-
例如上例中的`setTimeout`完成后的事件回调就存在任务队列中,这里需要说明的是浏览器定时计数器并不是由`JavaScript`引擎计数的,因为`JavaScript`引擎是单线程的,如果线程处于阻塞状态就会影响记计时的准确,计数是由浏览器线程进行计数的,当计数完毕,就将事件回调加入任务队列,同样`HTTP`请求在浏览器中也存在单独的线程,也是执行完毕后将事件回调置入任务队列。通过这个流程,就能够解释为什么上例中`setTimeout`的回调一直无法执行,是由于主线程也就是执行栈中的代码没有完成,不会去读取任务队列中的事件回调来执行,即使这个事件回调早已在任务队列中。
38+
39+
例如上例中的`setTimeout`完成后的事件回调就存在任务队列中,这里需要说明的是浏览器定时计数器并不是由`JavaScript`引擎计数的。因为`JavaScript`引擎是单线程的,如果线程处于阻塞状态就会影响记计时的准确,计数是由浏览器线程进行计数的,当计数完毕,就将事件回调加入任务队列。同样`HTTP`请求在浏览器中也存在单独的线程,也是执行完毕后将事件回调置入任务队列。通过这个流程,就能够解释为什么上例中`setTimeout`的回调一直无法执行,是由于主线程也就是执行栈中的代码没有完成,不会去读取任务队列中的事件回调来执行,即使这个事件回调早已在任务队列中。
3540

3641
### Event Loop
37-
主线程从任务队列中读取事件,这个过程是循环不断的,所以整个的这种运行机制又称为`Event Loop`,`Event Loop`是一个执行模型,在不同的地方有不同的实现,浏览器和`NodeJS`基于不同的技术实现了各自的`Event Loop`。浏览器的`Event Loop`是在`HTML5`的规范中明确定义,`NodeJS`的`Event Loop`是基于`libuv`实现的。
42+
主线程从任务队列中读取事件,这个过程是循环不断的,所以整个的这种运行机制又称为`Event Loop`,`Event Loop`是一个执行模型,在不同的地方有不同的实现,浏览器和`NodeJS`基于不同的技术实现了各自的`Event Loop`。浏览器的`Event Loop`是在`HTML5`的规范中明确定义,`NodeJS`的`Event Loop`是基于`libuv`实现的。
43+
3844
在浏览器中的`Event Loop`由执行栈`Execution Stack`、后台线程`Background Threads`、宏队列`Macrotask Queue`、微队列`Microtask Queue`组成。
3945

4046
* 执行栈就是在主线程执行同步任务的数据结构,函数调用形成了一个由若干帧组成的栈。
4147
* 后台线程就是浏览器实现对于`setTimeout`、`setInterval`、`XMLHttpRequest`等等的执行线程。
42-
* 宏队列,一些异步任务的回调会依次进入宏队列,等待后续被调用,包括`setTimeout`、`setInterval`、`setImmediate(Node)`、`requestAnimationFrame`、`UI rendering`、`I/O`等操作
43-
* 微队列,另一些异步任务的回调会依次进入微队列,等待后续调用,包括`Promise`、`process.nextTick(Node)`、`Object.observe`、`MutationObserver`等操作
44-
45-
当`Js`执行时,进行如下流程
46-
1. 首先将执行栈中代码同步执行,将这些代码中异步任务加入后台线程中
47-
2. 执行栈中的同步代码执行完毕后,执行栈清空,并开始扫描微队列
48-
3. 取出微队列队首任务,放入执行栈中执行,此时微队列是进行了出队操作
49-
4. 当执行栈执行完成后,继续出队微队列任务并执行,直到微队列任务全部执行完毕
50-
5. 最后一个微队列任务出队并进入执行栈后微队列中任务为空,当执行栈任务完成后,开始扫面微队列为空,继续扫描宏队列任务,宏队列出队,放入执行栈中执行,执行完毕后继续扫描微队列为空则扫描宏队列,出队执行
48+
* 宏队列,一些异步任务的回调会依次进入宏队列,等待后续被调用,包括`setTimeout`、`setInterval`、`setImmediate(Node)`、`requestAnimationFrame`、`UI rendering`、`I/O`等操作。
49+
* 微队列,另一些异步任务的回调会依次进入微队列,等待后续调用,包括`Promise`、`process.nextTick(Node)`、`Object.observe`、`MutationObserver`等操作。
50+
51+
当`Js`执行时,进行如下流程:
52+
53+
1. 首先将执行栈中代码同步执行,将这些代码中异步任务加入后台线程中。
54+
2. 执行栈中的同步代码执行完毕后,执行栈清空,并开始扫描微队列。
55+
3. 取出微队列队首任务,放入执行栈中执行,此时微队列是进行了出队操作。
56+
4. 当执行栈执行完成后,继续出队微队列任务并执行,直到微队列任务全部执行完毕。
57+
5. 最后一个微队列任务出队并进入执行栈后微队列中任务为空,当执行栈任务完成后,开始扫面微队列为空,继续扫描宏队列任务,宏队列出队,放入执行栈中执行,执行完毕后继续扫描微队列为空则扫描宏队列,出队执行。
5158
6. 不断往复...
5259

5360
#### 实例
@@ -95,14 +102,16 @@ console.log(7);
95102
*/
96103
```
97104

98-
##### Step 1
105+
#### Step 1
106+
99107
```javascript
100108
// 执行栈 console
101109
// 微队列 []
102110
// 宏队列 []
103111
console.log(1); // 1
104112
```
105-
##### Step 2
113+
#### Step 2
114+
106115
```javascript
107116
// 执行栈 setTimeout
108117
// 微队列 []
@@ -114,7 +123,8 @@ setTimeout(() => {
114123
});
115124
}, 0);
116125
```
117-
##### Step 3
126+
#### Step 3
127+
118128
```javascript
119129
// 执行栈 Promise
120130
// 微队列 [then1]
@@ -127,7 +137,8 @@ new Promise((resolve, reject) => {
127137
})
128138
```
129139

130-
##### Step 4
140+
#### Step 4
141+
131142
```javascript
132143
// 执行栈 setTimeout
133144
// 微队列 [then1]
@@ -137,23 +148,26 @@ setTimeout(() => {
137148
}, 0);
138149
```
139150

140-
##### Step 5
151+
#### Step 5
152+
141153
```javascript
142154
// 执行栈 console
143155
// 微队列 [then1]
144156
// 宏队列 [setTimeout1 setTimeout2]
145157
console.log(7); // 7
146158
```
147159

148-
##### Step 6
160+
#### Step 6
161+
149162
```javascript
150163
// 执行栈 then1
151164
// 微队列 []
152165
// 宏队列 [setTimeout1 setTimeout2]
153166
console.log(5); // 5
154167
```
155168

156-
##### Step 7
169+
#### Step 7
170+
157171
```javascript
158172
// 执行栈 setTimeout1
159173
// 微队列 [then2]
@@ -164,15 +178,17 @@ Promise.resolve().then(() => {
164178
});
165179
```
166180

167-
##### Step 8
181+
#### Step 8
182+
168183
```javascript
169184
// 执行栈 then2
170185
// 微队列 []
171186
// 宏队列 [setTimeout2]
172187
console.log(3); // 3
173188
```
174189

175-
##### Step 9
190+
#### Step 9
191+
176192
```javascript
177193
// 执行栈 setTimeout2
178194
// 微队列 []
@@ -182,18 +198,14 @@ console.log(6); // 6
182198

183199
## 每日一题
184200

185-
```
186-
https://github.com/WindrunnerMax/EveryDay
187-
```
201+
- <https://github.com/WindRunnerMax/EveryDay>
188202

189203

190204
## 参考
191205

192-
```
193-
https://www.jianshu.com/p/1a35857c78e5
194-
https://segmentfault.com/a/1190000016278115
195-
https://segmentfault.com/a/1190000012925872
196-
https://www.cnblogs.com/sunidol/p/11301808.html
197-
http://www.ruanyifeng.com/blog/2014/10/event-loop.html
198-
https://developer.mozilla.org/zh-CN/docs/Web/JavaScript/EventLoop
199-
```
206+
- <https://www.jianshu.com/p/1a35857c78e5>
207+
- <https://segmentfault.com/a/1190000016278115>
208+
- <https://segmentfault.com/a/1190000012925872>
209+
- <https://www.cnblogs.com/sunidol/p/11301808.html>
210+
- <http://www.ruanyifeng.com/blog/2014/10/event-loop.html>
211+
- <https://developer.mozilla.org/zh-CN/docs/Web/JavaScript/EventLoop>

‎JavaScript/Js模块化导入导出.md‎

Lines changed: 6 additions & 10 deletions
Original file line numberDiff line numberDiff line change
@@ -197,17 +197,13 @@ export default obj;
197197

198198
## 每日一题
199199

200-
```
201-
https://github.com/WindrunnerMax/EveryDay
202-
```
200+
- <https://github.com/WindRunnerMax/EveryDay>
203201

204202

205203
## 参考
206204

207-
```
208-
https://segmentfault.com/a/1190000010426778
209-
https://www.cnblogs.com/leftJS/p/11073481.html
210-
https://www.cnblogs.com/zhoulujun/p/9415407.html
211-
https://www.cnblogs.com/zhoulujun/p/9415407.html
212-
https://www.cnblogs.com/moxiaowohuwei/p/8692359.html
213-
```
205+
- <https://segmentfault.com/a/1190000010426778>
206+
- <https://www.cnblogs.com/leftJS/p/11073481.html>
207+
- <https://www.cnblogs.com/zhoulujun/p/9415407.html>
208+
- <https://www.cnblogs.com/zhoulujun/p/9415407.html>
209+
- <https://www.cnblogs.com/moxiaowohuwei/p/8692359.html>

‎JavaScript/async、await剖析.md‎

Lines changed: 12 additions & 11 deletions
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,5 @@
11
# async/await剖析
2-
`JavaScript`是单线程的,为了避免同步阻塞可能会带来的一些负面影响,引入了异步非阻塞机制,而对于异步执行的解决方案从最早的回调函数,到`ES6`的`Promise`对象以及`Generator`函数,每次都有所改进,但是却又美中不足,他们都有额外的复杂性,都需要理解抽象的底层运行机制,直到在`ES7`中引入了`async/await`,他可以简化使用多个`Promise`时的同步行为,在编程的时候甚至都不需要关心这个操作是否为异步操作。
2+
`JavaScript`是单线程的,为了避免同步阻塞可能会带来的一些负面影响,引入了异步非阻塞机制,而对于异步执行的解决方案从最早的回调函数,到`ES6`的`Promise`对象以及`Generator`函数,每次都有所改进,但是却又美中不足。他们都有额外的复杂性,都需要理解抽象的底层运行机制,直到在`ES7`中引入了`async/await`,他可以简化使用多个`Promise`时的同步行为,在编程的时候甚至都不需要关心这个操作是否为异步操作。
33

44
## 分析
55
首先使用`async/await`执行一组异步操作,并不需要回调嵌套也不需要写多个`then`方法,在使用上甚至觉得这本身就是一个同步操作,当然在正式使用上应该将`await`语句放置于` try...catch`代码块中,因为`await`命令后面的`Promise`对象,运行结果可能是`rejected`。
@@ -23,7 +23,10 @@ async function asyncFunct(){
2323

2424
asyncFunct();
2525
```
26-
`async/await`实际上是`Generator`函数的语法糖,如`Promises`类似于结构化回调,`async/await`在实现上结合了`Generator`函数与`Promise`函数,下面使用`Generator`函数加`Thunk`函数的形式实现一个与上边相同的例子,可以看到只是将`async`替换成了`*`放置在函数右端,并将`await`替换成了`yield`,所以说`async/await`实际上是`Generator`函数的语法糖,此处唯一不同的地方在于实现了一个流程的自动管理函数`run`,而`async/await`内置了执行器,关于这个例子的实现下边会详述。对比来看,`async`和`await`,比起`*`和`yield`,语义更清楚,`async`表示函数里有异步操作,`await`表示紧跟在后面的表达式需要等待结果。
26+
27+
`async/await`实际上是`Generator`函数的语法糖,如`Promises`类似于结构化回调,`async/await`在实现上结合了`Generator`函数与`Promise`函数,下面使用`Generator`函数加`Thunk`函数的形式实现一个与上边相同的例子,可以看到只是将`async`替换成了`*`放置在函数右端,并将`await`替换成了`yield`,所以说`async/await`实际上是`Generator`函数的语法糖。
28+
29+
此处唯一不同的地方在于实现了一个流程的自动管理函数`run`,而`async/await`内置了执行器,关于这个例子的实现下边会详述。对比来看,`async`和`await`,比起`*`和`yield`,语义更清楚,`async`表示函数里有异步操作,`await`表示紧跟在后面的表达式需要等待结果。
2730

2831
```javascript
2932
function thunkFunct(){
@@ -63,7 +66,9 @@ run(generator);
6366

6467
### Generator yield Thunk
6568

66-
自动流程管理`run`函数,首先需要知道在调用`next()`方法时,如果传入了参数,那么这个参数会传给上一条执行的`yield`语句左边的变量,在这个函数中,第一次执行`next`时并未传递参数,而且在第一个`yield`上边也并不存在接收变量的语句,无需传递参数,接下来就是判断是否执行完这个生成器函数,在这里并没有执行完,那么将自定义的`next`函数传入`res.value`中,这里需要注意`res.value`是一个函数,可以在下边的例子中将注释的那一行执行,然后就可以看到这个值是`f(funct){...}`,此时我们将自定义的`next`函数传递后,就将`next`的执行权限交予了`f`这个函数,在这个函数执行完异步任务后,会执行回调函数,在这个回调函数中会触发生成器的下一个`next`方法,并且这个`next`方法是传递了参数的,上文提到传入参数后会将其传递给上一条执行的`yield`语句左边的变量,那么在这一次执行中会将这个参数值传递给`r1`,然后在继续执行`next`,不断往复,直到生成器函数结束运行,这样就实现了流程的自动管理。
69+
自动流程管理`run`函数,首先需要知道在调用`next()`方法时,如果传入了参数,那么这个参数会传给上一条执行的`yield`语句左边的变量,在这个函数中,第一次执行`next`时并未传递参数,而且在第一个`yield`上边也并不存在接收变量的语句,无需传递参数。接下来就是判断是否执行完这个生成器函数,在这里并没有执行完,那么将自定义的`next`函数传入`res.value`中,这里需要注意`res.value`是一个函数,可以在下边的例子中将注释的那一行执行,然后就可以看到这个值是`f(funct){...}`。
70+
71+
此时我们将自定义的`next`函数传递后,就将`next`的执行权限交予了`f`这个函数,在这个函数执行完异步任务后,会执行回调函数,在这个回调函数中会触发生成器的下一个`next`方法,并且这个`next`方法是传递了参数的,上文提到传入参数后会将其传递给上一条执行的`yield`语句左边的变量,那么在这一次执行中会将这个参数值传递给`r1`,然后在继续执行`next`,不断往复,直到生成器函数结束运行,这样就实现了流程的自动管理。
6772

6873
```javascript
6974
function thunkFunct(){
@@ -186,14 +191,10 @@ run(generator).then( () => {
186191

187192
## 每日一题
188193

189-
```
190-
https://github.com/WindrunnerMax/EveryDay
191-
```
194+
- <https://github.com/WindRunnerMax/EveryDay>
192195

193196
## 参考
194197

195-
```
196-
https://segmentfault.com/a/1190000007535316
197-
http://www.ruanyifeng.com/blog/2015/05/co.html
198-
http://www.ruanyifeng.com/blog/2015/05/async.html
199-
```
198+
- <https://segmentfault.com/a/1190000007535316>
199+
- <http://www.ruanyifeng.com/blog/2015/05/co.html>
200+
- <http://www.ruanyifeng.com/blog/2015/05/async.html>

‎MyLife/记一次有意思的种树比赛.md‎

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -392,7 +392,7 @@ while(true){
392392
// // 注:变量cgi已在全局定义
393393
```
394394
395-
## 最后
395+
## 总结
396396
虽然写这个极其上头,但是还有很多事没做,比如老师给的论文下周要做汇报,玩了一下午先不玩了,在我写下这篇文章的时候已经有大佬种到`200w`棵了,我才种了`100w`,然后排行是`82`,在此仰望大佬们哈哈。
397397
398398
## Blog

0 commit comments

Comments
 (0)