-
Notifications
You must be signed in to change notification settings - Fork 0
Expand file tree
/
Copy pathsearch.xml
More file actions
1755 lines (1696 loc) · 155 KB
/
search.xml
File metadata and controls
1755 lines (1696 loc) · 155 KB
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
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
255
256
257
258
259
260
261
262
263
264
265
266
267
268
269
270
271
272
273
274
275
276
277
278
279
280
281
282
283
284
285
286
287
288
289
290
291
292
293
294
295
296
297
298
299
300
301
302
303
304
305
306
307
308
309
310
311
312
313
314
315
316
317
318
319
320
321
322
323
324
325
326
327
328
329
330
331
332
333
334
335
336
337
338
339
340
341
342
343
344
345
346
347
348
349
350
351
352
353
354
355
356
357
358
359
360
361
362
363
364
365
366
367
368
369
370
371
372
373
374
375
376
377
378
379
380
381
382
383
384
385
386
387
388
389
390
391
392
393
394
395
396
397
398
399
400
401
402
403
404
405
406
407
408
409
410
411
412
413
414
415
416
417
418
419
420
421
422
423
424
425
426
427
428
429
430
431
432
433
434
435
436
437
438
439
440
441
442
443
444
445
446
447
448
449
450
451
452
453
454
455
456
457
458
459
460
461
462
463
464
465
466
467
468
469
470
471
472
473
474
475
476
477
478
479
480
481
482
483
484
485
486
487
488
489
490
491
492
493
494
495
496
497
498
499
500
501
502
503
504
505
506
507
508
509
510
511
512
513
514
515
516
517
518
519
520
521
522
523
524
525
526
527
528
529
530
531
532
533
534
535
536
537
538
539
540
541
542
543
544
545
546
547
548
549
550
551
552
553
554
555
556
557
558
559
560
561
562
563
564
565
566
567
568
569
570
571
572
573
574
575
576
577
578
579
580
581
582
583
584
585
586
587
588
589
590
591
592
593
594
595
596
597
598
599
600
601
602
603
604
605
606
607
608
609
610
611
612
613
614
615
616
617
618
619
620
621
622
623
624
625
626
627
628
629
630
631
632
633
634
635
636
637
638
639
640
641
642
643
644
645
646
647
648
649
650
651
652
653
654
655
656
657
658
659
660
661
662
663
664
665
666
667
668
669
670
671
672
673
674
675
676
677
678
679
680
681
682
683
684
685
686
687
688
689
690
691
692
693
694
695
696
697
698
699
700
701
702
703
704
705
706
707
708
709
710
711
712
713
714
715
716
717
718
719
720
721
722
723
724
725
726
727
728
729
730
731
732
733
734
735
736
737
738
739
740
741
742
743
744
745
746
747
748
749
750
751
752
753
754
755
756
757
758
759
760
761
762
763
764
765
766
767
768
769
770
771
772
773
774
775
776
777
778
779
780
781
782
783
784
785
786
787
788
789
790
791
792
793
794
795
796
797
798
799
800
801
802
803
804
805
806
807
808
809
810
811
812
813
814
815
816
817
818
819
820
821
822
823
824
825
826
827
828
829
830
831
832
833
834
835
836
837
838
839
840
841
842
843
844
845
846
847
848
849
850
851
852
853
854
855
856
857
858
859
860
861
862
863
864
865
866
867
868
869
870
871
872
873
874
875
876
877
878
879
880
881
882
883
884
885
886
887
888
889
890
891
892
893
894
895
896
897
898
899
900
901
902
903
904
905
906
907
908
909
910
911
912
913
914
915
916
917
918
919
920
921
922
923
924
925
926
927
928
929
930
931
932
933
934
935
936
937
938
939
940
941
942
943
944
945
946
947
948
949
950
951
952
953
954
955
956
957
958
959
960
961
962
963
964
965
966
967
968
969
970
971
972
973
974
975
976
977
978
979
980
981
982
983
984
985
986
987
988
989
990
991
992
993
994
995
996
997
998
999
1000
<?xml version="1.0" encoding="utf-8"?>
<search>
<entry>
<title><![CDATA[2017 Plan]]></title>
<url>http://blog.dzyhenry.com/2017/12/31/2017/</url>
<content type="html"><![CDATA[<h2 id="JavaScript"><a href="#JavaScript" class="headerlink" title="JavaScript"></a>JavaScript</h2><ul>
<li>JavaScript: <a href="http://blog.dzyhenry.com/2017/01/15/ecma_learing/">Dmitry Soshnikov’s ECMAScript Analysis</a></li>
<li>JavaScript Asyncronous Programming, <a href="https://github.com/yahoo/ypromise/blob/master/promise.js" target="_blank" rel="external">yui-promise</a></li>
<li><a href="http://purplebamboo.github.io/2015/01/17/javascript-module/" target="_blank" rel="external">Module Loader</a></li>
<li>MVVM<ul>
<li><a href="https://zhuanlan.zhihu.com/p/24435564" target="_blank" rel="external">不造个轮子,你还真以为你会写代码了?</a></li>
<li><a href="https://zhuanlan.zhihu.com/p/24475845?refer=mirone" target="_blank" rel="external">250行实现一个简单的MVVM</a></li>
</ul>
</li>
<li><a href="https://developer.mozilla.org/en-US/docs/Web/JavaScript/Guide/Regular_Expressions" target="_blank" rel="external">Regular Expression</a><a id="more"></a>
</li>
</ul>
<h2 id="Node-js"><a href="#Node-js" class="headerlink" title="Node.js"></a><a href="https://nodejs.org/en/" target="_blank" rel="external">Node.js</a></h2><ul>
<li><p>Node.js Official Documentations</p>
<ul>
<li><a href="https://nodejs.org/dist/latest-v7.x/docs/api/buffer.html" target="_blank" rel="external">Buffer</a></li>
<li><a href="https://nodejs.org/dist/latest-v7.x/docs/api/stream.html" target="_blank" rel="external">Stream</a></li>
<li><a href="https://nodejs.org/dist/latest-v7.x/docs/api/cluster.html" target="_blank" rel="external">Cluster</a></li>
<li><a href="https://nodejs.org/dist/latest-v7.x/docs/api/child_process.html" target="_blank" rel="external">child_proess</a></li>
<li><a href="https://nodejs.org/dist/latest-v7.x/docs/api/addons.html#addons_addons" target="_blank" rel="external">C/C++ Addons</a>, <a href="http://taobaofed.org/blog/2016/09/20/type-casts-between-node-and-cpp/" target="_blank" rel="external">Node.js 和 C++ 之间的类型转换</a></li>
</ul>
</li>
<li><p><a href="https://github.com/substack/hyperquest" target="_blank" rel="external">hyperquest</a> source code</p>
</li>
<li><p><a href="https://github.com/koajs/koa" target="_blank" rel="external">KOA</a> source code</p>
</li>
<li><p>Deep learning of Node.js</p>
<ul>
<li><a href="http://nikhilm.github.io/uvbook/index.html" target="_blank" rel="external">An Introduction to libuv</a> <h2 id="Webpack"><a href="#Webpack" class="headerlink" title="Webpack"></a><a href="https://webpack.github.io/" target="_blank" rel="external">Webpack</a></h2></li>
</ul>
</li>
<li><a href="http://taobaofed.org/blog/2016/09/09/webpack-flow/" target="_blank" rel="external">细说 webpack 之流程篇</a></li>
<li><a href="http://www.alloyteam.com/2016/01/webpack-loader-1/" target="_blank" rel="external">如何开发一个webpack loader</a></li>
<li><a href="https://segmentfault.com/a/1190000003506497" target="_blank" rel="external">What、Why、How?解读Webpack官方文档</a></li>
</ul>
<h2 id="Vue-js"><a href="#Vue-js" class="headerlink" title="Vue.js"></a><a href="https://vuejs.org/v2/guide/" target="_blank" rel="external">Vue.js</a></h2><h2 id="Python"><a href="#Python" class="headerlink" title="Python"></a><a href="https://www.python.org/" target="_blank" rel="external">Python</a></h2><h2 id="CSS"><a href="#CSS" class="headerlink" title="CSS"></a>CSS</h2><ul>
<li><a href="http://sass-lang.com/" target="_blank" rel="external">sass</a></li>
<li><a href="https://github.com/css-modules/css-modules" target="_blank" rel="external">css-modules</a>, <a href="https://github.com/css-modules/css-modules/issues/84" target="_blank" rel="external">css-modules/issues/84</a></li>
<li><a href="https://developer.mozilla.org/en-US/docs/Web/CSS/flex" target="_blank" rel="external">Flex</a></li>
</ul>
]]></content>
</entry>
<entry>
<title><![CDATA[Dmitry Soshnikov's ECMAScript Analysis]]></title>
<url>http://blog.dzyhenry.com/2017/01/15/ecma_learing/</url>
<content type="html"><![CDATA[<p><strong>If you want to learn JavaScript deeply and professionally (at theoretical level of the ECMAScript), these would be the best gift for you.</strong><br>Since the original articles are somehow scattered, here we gather them together.<br><a id="more"></a></p>
<h2 id="ECAMScript-262-3"><a href="#ECAMScript-262-3" class="headerlink" title="ECAMScript-262-3"></a>ECAMScript-262-3</h2><ul>
<li><a href="http://dmitrysoshnikov.com/ecmascript/chapter-1-execution-contexts/" target="_blank" rel="external">ECMA-262-3 in detail. Chapter 1. Execution Contexts.</a></li>
<li><a href="http://dmitrysoshnikov.com/ecmascript/chapter-2-variable-object/" target="_blank" rel="external">ECMA-262-3 in detail. Chapter 2. Variable object.</a></li>
<li><a href="http://dmitrysoshnikov.com/ecmascript/chapter-3-this/" target="_blank" rel="external">ECMA-262-3 in detail. Chapter 3. This.</a></li>
<li><a href="http://dmitrysoshnikov.com/ecmascript/chapter-4-scope-chain/" target="_blank" rel="external">ECMA-262-3 in detail. Chapter 4. Scope chain.</a></li>
<li><a href="http://dmitrysoshnikov.com/ecmascript/chapter-5-functions/" target="_blank" rel="external">ECMA-262-3 in detail. Chapter 5. Functions.</a></li>
<li><a href="http://dmitrysoshnikov.com/ecmascript/chapter-6-closures/" target="_blank" rel="external">ECMA-262-3 in detail. Chapter 6. Closures.</a></li>
<li><a href="http://dmitrysoshnikov.com/ecmascript/chapter-7.1-oop-general-theory/" target="_blank" rel="external">ECMA-262-3 in detail. Chapter 7.1. OOP: The general theory.</a></li>
<li><a href="http://dmitrysoshnikov.com/ecmascript/chapter-7-2-oop-ecmascript-implementation/" target="_blank" rel="external">ECMA-262-3 in detail. Chapter 7.2. OOP: ECMAScript implementation.</a></li>
<li><a href="http://dmitrysoshnikov.com/ecmascript/chapter-8-evaluation-strategy/" target="_blank" rel="external">ECMA-262-3 in detail. Chapter 8. Evaluation strategy.</a></li>
</ul>
<h2 id="ECMAScript-262-5"><a href="#ECMAScript-262-5" class="headerlink" title="ECMAScript-262-5"></a>ECMAScript-262-5</h2><ul>
<li><a href="http://dmitrysoshnikov.com/ecmascript/es5-chapter-0-introduction/" target="_blank" rel="external">ECMA-262-5 in detail. Chapter 0. Introduction.</a></li>
<li><a href="http://dmitrysoshnikov.com/ecmascript/es5-chapter-1-properties-and-property-descriptors/" target="_blank" rel="external">ECMA-262-5 in detail. Chapter 1. Properties and Property Descriptors.</a></li>
<li><a href="http://dmitrysoshnikov.com/ecmascript/es5-chapter-2-strict-mode/" target="_blank" rel="external">ECMA-262-5 in detail. Chapter 2. Strict Mode.</a></li>
<li><a href="http://dmitrysoshnikov.com/ecmascript/es5-chapter-3-1-lexical-environments-common-theory/" target="_blank" rel="external">ECMA-262-5 in detail. Chapter 3.1. Lexical environments: Common Theory.</a></li>
<li><a href="http://dmitrysoshnikov.com/ecmascript/es5-chapter-3-2-lexical-environments-ecmascript-implementation/" target="_blank" rel="external">ECMA-262-5 in detail. Chapter 3.2. Lexical environments: ECMAScript implementation.</a></li>
</ul>
<h2 id="Note"><a href="#Note" class="headerlink" title="Note"></a>Note</h2><ul>
<li><a href="http://dmitrysoshnikov.com/notes/note-1-ecmascript-bound-functions/" target="_blank" rel="external">Note 1. ECMAScript. Bound functions.</a></li>
<li><a href="http://dmitrysoshnikov.com/notes/note-2-ecmascript-equality-operators/" target="_blank" rel="external">Note 2. ECMAScript. Equality operators.</a></li>
<li><a href="http://dmitrysoshnikov.com/notes/note-4-two-words-about-hoisting/" target="_blank" rel="external">Note 4. Two words about “hoisting”.</a></li>
<li><a href="http://dmitrysoshnikov.com/notes/unresolved-references/" target="_blank" rel="external">Notes. ECMAScript: Unresolved references</a></li>
<li><a href="http://dmitrysoshnikov.com/ecmascript/es6-notes-default-values-of-parameters/" target="_blank" rel="external">ES6 Notes: Default values of parameters</a></li>
<li><a href="http://dmitrysoshnikov.com/notes/pattern-matching/" target="_blank" rel="external">Pattern Matching</a></li>
<li><a href="https://medium.com/@DmitrySoshnikov/oo-relationships-5020163ab162#.iynhkwp4k" target="_blank" rel="external">OO Relationships</a></li>
</ul>
<h2 id="Some-Personal-Abstract"><a href="#Some-Personal-Abstract" class="headerlink" title="Some Personal Abstract"></a>Some Personal Abstract</h2><blockquote>
<p>A special data structure of the call-stack which is called an activation record is used as a storage ot the environment bindings. Sometimes it’s also called a call-stack frame.<br>– from <code>ECMA-262-5 in detail. Chapter 3.1. Lexical environments: Commo Theory.</code></p>
<p>One of the terminologies used in the theory for the activatoin objects in <code>environment frames</code>(analogy with call-statck frames). We use this terminology to underline the differences of implementation - that environment frames continue to exists if there are references to them from closures. Also we use this terminology to underline the higher-abstracted concepts - i.e. without concentrating on lower level stack and address structures, we just say that there are environments, and how they are implemented - is already a derived question.<br>– from <code>ECMA-262-5 in detail. Chapter 3.1. Lexical environments: Commo Theory.</code></p>
</blockquote>
]]></content>
</entry>
<entry>
<title><![CDATA[Node.js学习笔记 - HTTP]]></title>
<url>http://blog.dzyhenry.com/2017/01/15/http/</url>
<content type="html"><![CDATA[<p><a href="https://nodejs.org/dist/latest-v7.x/docs/api/http.html" target="_blank" rel="external">HTTP</a>是Node.js的一个非常重要模块,为搭建HTTP服务提供了非常便利的API,通过HTTP模块,我们可以用短短地十几行代码搭建起一个HTTP Server。</p>
<p>在我看来,HTTP模块是Node.js中一个偏应用层的模块,依赖于EventEmitter、Stream、Net等模块。该模块替应用开发者处理了很多HTTP请求中的细节,文档中的描述主要围绕怎样合理地处理<code>request</code>和<code>response</code>。在学习的同时,也让我了解了HTTP协议中的诸多细节。</p>
<a id="more"></a>
<ul>
<li><a href="https://nodejs.org/dist/latest-v7.x/docs/api/http.html#http_class_http_agent" target="_blank" rel="external">http.Agent</a>: 管理HTTP client Request中使用的socket池的子模块</li>
<li><a href="https://nodejs.org/dist/latest-v7.x/docs/api/http.html#http_class_http_clientrequest" target="_blank" rel="external">http.ClientRequest</a>: 一个发送HTTP请求的客户端实例,通过<code>http.request()</code>或者<code>http.get()</code>返回。实现了<a href="https://nodejs.org/dist/latest-v7.x/docs/api/stream.html#stream_class_stream_writable" target="_blank" rel="external">Writable Stream</a>,继承了<a href="https://nodejs.org/dist/latest-v7.x/docs/api/events.html#events_class_eventemitter" target="_blank" rel="external">EventEmitter</a></li>
<li><a href="https://nodejs.org/dist/latest-v7.x/docs/api/http.html#http_class_http_server" target="_blank" rel="external">http.Server</a>: 一个能够处理HTTP请求的Server实例,通过http.createServer返回。继承了<a href="https://nodejs.org/dist/latest-v7.x/docs/api/net.html#net_class_net_server" target="_blank" rel="external">net.Server</a>,新增了一些API和事件。</li>
<li><a href="https://nodejs.org/dist/latest-v7.x/docs/api/http.html#http_class_http_serverresponse" target="_blank" rel="external">http.ServerResponse</a>: Node server创建的并处理请求的‘响应对象’。继承自<a href="https://nodejs.org/dist/latest-v7.x/docs/api/events.html#events_class_eventemitter" target="_blank" rel="external">EventEmitter</a>,实现了<a href="https://nodejs.org/dist/latest-v7.x/docs/api/stream.html#stream_class_stream_writable" target="_blank" rel="external">Writable Stream</a>。</li>
<li><a href="https://nodejs.org/dist/latest-v7.x/docs/api/http.html#http_class_http_incomingmessage" target="_blank" rel="external">http.IncomingMessage</a>: <code>Readable Stream</code></li>
</ul>
<h2 id="Class-http-Agent"><a href="#Class-http-Agent" class="headerlink" title="Class: http.Agent"></a>Class: <a href="https://nodejs.org/dist/latest-v7.x/docs/api/http.html#http_class_http_agent" target="_blank" rel="external">http.Agent</a></h2><blockquote>
<p>The HTTP Agent is used for pooling sockets used in HTTP client requests.</p>
</blockquote>
<h3 id="agent-createConnection-options-callback"><a href="#agent-createConnection-options-callback" class="headerlink" title="agent.createConnection(options[, callback])"></a>agent.createConnection(options[, callback])</h3><ul>
<li><code>options<Object></code></li>
<li><code>callback<Function></code></li>
</ul>
<p>创建一个用于HTTP请求的socket或stream。该函数返回一个socket或stream。</p>
<p><code>callback</code>的函数签名形式是:<code>(err, stream)</code> </p>
<h3 id="agent-destroy"><a href="#agent-destroy" class="headerlink" title="agent.destroy()"></a>agent.destroy()</h3><p>销毁该agent的所有socket连接</p>
<h3 id="agent-getName"><a href="#agent-getName" class="headerlink" title="agent.getName()"></a>agent.getName()</h3><blockquote>
<p>Get a unique name for a set of request options, to determine whether a connection can be reused. In the http agent, this returns host:port:localAddress. In the https agent, the name includes the CA, cert, ciphers, and other HTTPS/TLS-specific options that determine socket reusability.</p>
</blockquote>
<h3 id="agent-maxFreeSockets"><a href="#agent-maxFreeSockets" class="headerlink" title="agent.maxFreeSockets"></a>agent.maxFreeSockets</h3><p>设置agent处于free状态时的最大socket数量。(默认值是256)</p>
<h3 id="agent-maxSockets"><a href="#agent-maxSockets" class="headerlink" title="agent.maxSockets"></a>agent.maxSockets</h3><p>设置该agent与同一个<code>origin(host:port)</code>能够同时连接的最大的socket数量。(默认Infinity)</p>
<h3 id="agent-requests"><a href="#agent-requests" class="headerlink" title="agent.requests"></a>agent.requests</h3><blockquote>
<p>An object which contains queues of requests that have not yet been assigned to sockets. Do not modify.</p>
</blockquote>
<h3 id="agent-sockets"><a href="#agent-sockets" class="headerlink" title="agent.sockets"></a>agent.sockets</h3><blockquote>
<p>An object which contains arrays of sockets currently in use by the Agent. Do not modify.</p>
</blockquote>
<h2 id="Class-http-ClientRequest"><a href="#Class-http-ClientRequest" class="headerlink" title="Class: http.ClientRequest"></a>Class: <a href="https://nodejs.org/dist/latest-v7.x/docs/api/http.html#http_class_http_clientrequest" target="_blank" rel="external">http.ClientRequest</a></h2><p><code>ClientRequest</code>对象是Node.js内部创建并由<a href="https://nodejs.org/dist/latest-v7.x/docs/api/http.html#http_http_request_options_callback" target="_blank" rel="external">http.request()</a>方法返回。用于表示一个头部(header)已经进入”队列”并处于进行中(in-progress)的HTTP请求。</p>
<h3 id="Event-‘abort’"><a href="#Event-‘abort’" class="headerlink" title="Event: ‘abort’"></a>Event: ‘abort’</h3><p>当一个请求被客户端中止时触发。</p>
<blockquote>
<p>This event is only emitted on the first call to abort().</p>
</blockquote>
<h3 id="Event-‘aborted’"><a href="#Event-‘aborted’" class="headerlink" title="Event: ‘aborted’"></a>Event: ‘aborted’</h3><p>当请求被server中止且socket关闭时触发。</p>
<h3 id="Event-‘connect’"><a href="#Event-‘connect’" class="headerlink" title="Event: ‘connect’"></a>Event: ‘connect’</h3><p>当server端通过<code>CONNECT</code>方法响应一个请求时触发。</p>
<p>下面的例子来自<a href="https://nodejs.org/dist/latest-v7.x/docs/api/http.html#http_event_connect" target="_blank" rel="external">官方文档</a></p>
<pre><code class="javascript">/* eslint no-console: 0*/
const http = require('http');
const net = require('net');
const url = require('url');
const proxy = http.createServer((req, res) => {
res.writeHead(200, { 'Content-Type': 'text/plain' });
res.end('okay');
});
proxy.on('connect', (req, cltSocket, head) => {
const srvUrl = url.parse(`http://${req.url}`);
const srvSocket = net.connect(srvUrl.port, srvUrl.hostname, () => {
cltSocket.write('HTTP/1.1 200 Connection Established\r\n' +
'Proxy-agent: Node.js-Proxy\r\n' +
'\r\n');
});
srvSocket.write(head);
srvSocket.pipe(cltSocket);
cltSocket.pipe(srvSocket);
});
proxy.listen(1337, '127.0.0.1', () => {
const options = {
port: 1337,
hostname: '127.0.0.1',
method: 'CONNECT',
path: 'www.google.com:80',
};
// 返回一个ClientRequest对象
const req = http.request(options);
req.end();
req.on('connect', (res, socket) => {
console.log('got connected!');
// \r\n表示换行,具体可参考[回车和换行](http://www.ruanyifeng.com/blog/2006/04/post_213.html)
socket.write('GET / HTTP/1.1\r\n' +
'HOST: www.google.com:80\r\n' +
'Connection: close\r\n' +
'\r\n');
socket.on('data', (chunk) => {
console.log('###socket on data###', chunk.toString());
});
socket.on('end', () => {
proxy.close();
});
});
});
</code></pre>
<h3 id="Event-‘continue’"><a href="#Event-‘continue’" class="headerlink" title="Event: ‘continue’"></a>Event: ‘continue’</h3><p>当server响应<code>100 CONTINUE</code>时触发</p>
<h3 id="Event-‘response’"><a href="#Event-‘response’" class="headerlink" title="Event: ‘response’"></a>Event: ‘response’</h3><p>当请求接受到响应时触发,该事件仅会触发一次。</p>
<h3 id="Event-‘socket’"><a href="#Event-‘socket’" class="headerlink" title="Event: ‘socket’"></a>Event: ‘socket’</h3><p>当一个socket关联到该请求时触发</p>
<h3 id="Event-‘upgrade’"><a href="#Event-‘upgrade’" class="headerlink" title="Event: ‘upgrade’"></a>Event: ‘upgrade’</h3><p>当接收到server端的Upgrade响应头时触发。</p>
<p><a href="https://nodejs.org/dist/latest-v7.x/docs/api/http.html#http_event_upgrade" target="_blank" rel="external">官方示例</a></p>
<pre><code class="javascript">/* eslint no-console: 0 */
const http = require('http');
const server = http.createServer((req, res) => {
res.writeHead('200', { 'Content-Type': 'text/plain' });
res.end('okay');
});
server.on('upgrade', (req, socket) => {
socket.write('HTTP/1.1 101 Web Socket Protocol Handshake\r\n' +
'Upgrade: WebSocket\r\n' +
'Connection: Upgrade\r\n' +
'\r\n');
socket.pipe(socket);
});
server.listen(1337, '127.0.0.1', () => {
const options = {
port: 1337,
hostname: '127.0.0.1',
headers: {
Connection: 'Upgrade',
Upgrade: 'websocket',
},
};
const req = http.request(options);
req.end();
req.on('upgrade', (res, socket) => {
console.log('got upgrade!');
socket.end();
process.exit(0);
});
});
</code></pre>
<h3 id="request-abort"><a href="#request-abort" class="headerlink" title="request.abort()"></a>request.abort()</h3><blockquote>
<p>Marks the request as aborting. Calling this will cause remaining data in the response to be dropped and the socket to be destroyed.</p>
</blockquote>
<h3 id="request-end-data-encoding-callback"><a href="#request-end-data-encoding-callback" class="headerlink" title="request.end([data][, encoding][, callback])"></a>request.end([data][, encoding][, callback])</h3><ul>
<li><code>data<String|Buffer></code></li>
<li><code>encoding<String></code></li>
<li><code>callback<Function></code></li>
</ul>
<blockquote>
<p>Finishes sending the request. If any parts of the body are unsent, it will flush them to the stream. If the request is chunked, this will send the terminating ‘0\r\n\r\n’.</p>
</blockquote>
<p>如果有<code>data</code>参数,则等同于在<code>request.write(data, encoding)</code>之后调用<code>request.end(callback)</code></p>
<p>callack在请求的stream结束以后调用。</p>
<h3 id="request-flushHeaders"><a href="#request-flushHeaders" class="headerlink" title="request.flushHeaders()"></a>request.flushHeaders()</h3><p>flush(直接发送)缓存的headers,从而绕过对于headers优化。</p>
<blockquote>
<p>For efficiency reasons, Node.js normally buffers the request headers until you call request.end() or write the first chunk of request data. It then tries hard to pack the request headers and data into a single TCP packet.</p>
</blockquote>
<h3 id="request-setTimeout-timeout-callback"><a href="#request-setTimeout-timeout-callback" class="headerlink" title="request.setTimeout(timeout[, callback])"></a>request.setTimeout(timeout[, callback])</h3><ul>
<li><code>timeout<Number></code></li>
<li><code>callback<Function></code>,当超时发生时触发</li>
</ul>
<p>设置请求的超时时间</p>
<h3 id="request-write-chunk-encoding-callback"><a href="#request-write-chunk-encoding-callback" class="headerlink" title="request.write(chunk[, encoding][, callback])"></a>request.write(chunk[, encoding][, callback])</h3><ul>
<li><code>chunk<Buffer|String></code></li>
<li><code>encoding<String></code></li>
<li><code>callback<Function></code></li>
</ul>
<h2 id="Class-http-Server"><a href="#Class-http-Server" class="headerlink" title="Class: http.Server"></a>Class: http.Server</h2><blockquote>
<p>This class inherits from <a href="https://nodejs.org/dist/latest-v7.x/docs/api/net.html#net_class_net_server" target="_blank" rel="external">net.Server</a>.</p>
</blockquote>
<h3 id="Event-‘checkContinue’"><a href="#Event-‘checkContinue’" class="headerlink" title="Event: ‘checkContinue’"></a>Event: ‘checkContinue’</h3><ul>
<li><code>request<IncomingMessage></code></li>
<li><code>response<http.ServerResponse></code></li>
</ul>
<p>当HTTP请求的header中有<code>Expect: 100-continue</code>时触发。</p>
<blockquote>
<p>Note that when this event is emitted and handled, the ‘request’ event will not be emitted.</p>
</blockquote>
<p>下面是一个示例</p>
<pre><code class="javascript">/* eslint no-console: 0 */
const http = require('http');
const server = http.createServer((req, res) => {
res.writeHead(200, { 'Content-Type': 'text/plain' });
res.end('okay');
});
server.on('checkContinue', (req, res) => {
console.log('checkContinue got!');
res.writeContinue();
});
server.listen(1337, () => {
const options = {
port: 1337,
hostname: '127.0.0.1',
headers: {
Expect: '100-continue',
},
};
const req = http.request(options);
req.end();
});
</code></pre>
<h3 id="Event-‘checkExpectation’"><a href="#Event-‘checkExpectation’" class="headerlink" title="Event: ‘checkExpectation’"></a>Event: ‘checkExpectation’</h3><ul>
<li><code>request<http.ClientRequest></code></li>
<li><code>response<http.ServerResponse></code></li>
</ul>
<p>当HTTP请求头中有<code>Expect</code>字段,且value中没有<code>100-continue</code>时触发。</p>
<blockquote>
<p>Note that when this event is emitted and handled, the ‘request’ event will not be emitted.</p>
</blockquote>
<h3 id="Event-‘clientError’"><a href="#Event-‘clientError’" class="headerlink" title="Event: ‘clientError’"></a>Event: ‘clientError’</h3><ul>
<li><code>exception<Error></code></li>
<li><code>socket<net.Socket></code></li>
</ul>
<p>正常来讲,一个HTTP请求因为客户端的错误而中断,Server端应该关闭Socket相应的<code>Socket</code>。为了更加优雅地处理这种场景,我们可以在关闭链接的同时以<code>400 Bad Request</code>响应客户端,从而避免唐突地关闭链接。</p>
<h3 id="Event-‘close’"><a href="#Event-‘close’" class="headerlink" title="Event: ‘close’"></a>Event: ‘close’</h3><p>当server close的时候触发</p>
<h3 id="Event-‘connect’-1"><a href="#Event-‘connect’-1" class="headerlink" title="Event: ‘connect’"></a>Event: ‘connect’</h3><ul>
<li><code>request<http.IncomingMessage></code></li>
<li><code>socket<net.Socket></code></li>
<li><code>head<Buffer></code>, The first packet of the tunneling stream (may be empty)</li>
</ul>
<p>当Server端接收到的HTTP请求中<code>method</code>是<code>connect</code>时触发。</p>
<blockquote>
<p>After this event is emitted, the request’s socket will not have a ‘data’ event listener, meaning you will need to bind to it in order to handle data sent to the server on that socket.</p>
</blockquote>
<h3 id="Event-‘connection’"><a href="#Event-‘connection’" class="headerlink" title="Event: ‘connection’"></a>Event: ‘connection’</h3><ul>
<li><code>socket<net.Socket></code><br>当一个新的TCP Steam创建时触发。</li>
</ul>
<h3 id="Event-‘request’"><a href="#Event-‘request’" class="headerlink" title="Event: ‘request’"></a>Event: ‘request’</h3><ul>
<li><code>request<http.IncomingMessage></code></li>
<li><code>response<http.ServerResponse></code></li>
</ul>
<blockquote>
<p>Emitted each time there is a request. Note that there may be multiple requests per connection (in the case of keep-alive connections).</p>
</blockquote>
<h3 id="server-close-callback"><a href="#server-close-callback" class="headerlink" title="server.close([callback])"></a>server.close([callback])</h3><ul>
<li><code>callback<Function></code><br>调用后server将不再处理新的HTTP请求,将继续处理已经接收的请求。</li>
</ul>
<h3 id="server-listening"><a href="#server-listening" class="headerlink" title="server.listening"></a>server.listening</h3><ul>
<li><code><Boolean></code></li>
</ul>
<p>返回一个bool值表示当前server是否在监听请求</p>
<h3 id="server-maxHeadersCount"><a href="#server-maxHeadersCount" class="headerlink" title="server.maxHeadersCount"></a>server.maxHeadersCount</h3><ul>
<li><code><Number></code><br>设置处理请求的headers的最大数量限制,默认1000。</li>
</ul>
<h3 id="server-setTimeout-msecs-callback"><a href="#server-setTimeout-msecs-callback" class="headerlink" title="server.setTimeout(msecs, callback)"></a>server.setTimeout(msecs, callback)</h3><ul>
<li><code>msecs<Number></code></li>
<li><code>callback<Function></code></li>
</ul>
<p>为server的<code>sockets</code>设置超时时间,当<code>socket</code>超时以后会调用<code>callback</code></p>
<h3 id="server-timeout"><a href="#server-timeout" class="headerlink" title="server.timeout"></a>server.timeout</h3><ul>
<li><code><Nubmer> Default = 120000(2 minutes)</code></li>
</ul>
<p>为后续的连接(connection)设置超时时间</p>
<blockquote>
<p>Set to 0 to disable any kind of automatic timeout behavior on incoming connections.</p>
</blockquote>
<h2 id="http-ServerResponse"><a href="#http-ServerResponse" class="headerlink" title="http.ServerResponse"></a>http.ServerResponse</h2><p>response是HTTP Server内部创建的对象,<a href="https://nodejs.org/dist/latest-v7.x/docs/api/http.html#http_event_request" target="_blank" rel="external">request</a>事件的第二个参数。<br>response对象实现了<a href="https://nodejs.org/dist/latest-v7.x/docs/api/stream.html#stream_class_stream_writable" target="_blank" rel="external">Writable Stream</a>接口,继承了<a href="https://nodejs.org/dist/latest-v7.x/docs/api/events.html#events_class_eventemitter" target="_blank" rel="external">EventEmitter</a>对象。</p>
<h3 id="Event-‘close’-1"><a href="#Event-‘close’-1" class="headerlink" title="Event: ‘close’"></a>Event: ‘close’</h3><blockquote>
<p>Indicates that the underlying connection was terminated before response.end() was called or able to flush.</p>
</blockquote>
<h3 id="Event-‘finish’"><a href="#Event-‘finish’" class="headerlink" title="Event: ‘finish’"></a>Event: ‘finish’</h3><p>当请求结束的时候触发此事件。</p>
<blockquote>
<p>After this event, no more events will be emitted on the response object.</p>
</blockquote>
<h3 id="response-addTrailers-headers"><a href="#response-addTrailers-headers" class="headerlink" title="response.addTrailers(headers)"></a>response.addTrailers(headers)</h3><ul>
<li><code>headers<Object></code></li>
</ul>
<blockquote>
<p>This method adds HTTP trailing headers (a header but at the end of the message) to the response.</p>
</blockquote>
<h3 id="response-end-data-encoding-callback"><a href="#response-end-data-encoding-callback" class="headerlink" title="response.end([data][, encoding][, callback])"></a>response.end([data][, encoding][, callback])</h3><ul>
<li><code>data<Buffer|String></code></li>
<li><code>encoding<String></code></li>
<li><code>callback<Function></code></li>
</ul>
<p><code>response.end()</code>方法的调用表示该请求的结束。<strong>每一个响应都必须调用<code>response.end()</code>来结束该response。</strong></p>
<blockquote>
<p>This method signals to the server that all of the response headers and body have been sent; that server should consider this message complete. The method, response.end(), MUST be called on each response.</p>
</blockquote>
<h3 id="response-finished"><a href="#response-finished" class="headerlink" title="response.finished"></a>response.finished</h3><ul>
<li><code><Boolean></code></li>
</ul>
<p>标识请求是否已经完成</p>
<h3 id="response-getHeader-name"><a href="#response-getHeader-name" class="headerlink" title="response.getHeader(name)"></a>response.getHeader(name)</h3><ul>
<li><code>name<String></code></li>
</ul>
<p>返回指定的请求头,name参数不区分大小写</p>
<h3 id="response-headerSent"><a href="#response-headerSent" class="headerlink" title="response.headerSent"></a>response.headerSent</h3><ul>
<li><code><Boolean></code></li>
</ul>
<p>标识请求头是否已经发送</p>
<h3 id="response-removeHeader-name"><a href="#response-removeHeader-name" class="headerlink" title="response.removeHeader(name)"></a>response.removeHeader(name)</h3><ul>
<li><code>name<String></code></li>
</ul>
<blockquote>
<p>Removes a header that’s queued for implicit sending.</p>
</blockquote>
<h3 id="response-setHeader-name-value"><a href="#response-setHeader-name-value" class="headerlink" title="response.setHeader(name, value)"></a>response.setHeader(name, value)</h3><ul>
<li><code>name<String></code></li>
<li><code>value<String></code></li>
</ul>
<p>设置单个相应头信息,优先级比<code>response.writeHead()</code>低。</p>
<pre><code class="javascript">// example
response.setHeader('Content-Type', 'text/html');
</code></pre>
<p>or</p>
<pre><code class="javascript">response.setHeader('Set-Cookie', ['type=ninja', 'language=javascript']);
</code></pre>
<h3 id="response-setTimeout-msecs-callback"><a href="#response-setTimeout-msecs-callback" class="headerlink" title="response.setTimeout(msecs, callback)"></a>response.setTimeout(msecs, callback)</h3><ul>
<li><code>msecs<Number></code></li>
<li><code>callback<Function></code></li>
</ul>
<p>设置Socket的超时时间。</p>
<blockquote>
<p>If no ‘timeout’ listener is added to the request, the response, or the server, then sockets are destroyed when they time out. If you assign a handler on the request, the response, or the server’s ‘timeout’ events, then it is your responsibility to handle timed out sockets.</p>
</blockquote>
<h3 id="response-statusCode"><a href="#response-statusCode" class="headerlink" title="response.statusCode"></a>response.statusCode</h3><ul>
<li><code><Number></code></li>
</ul>
<p>为响应设置状态码</p>
<pre><code class="javascript">// example
response.statusCode = 404;
</code></pre>
<h3 id="response-statusMessage"><a href="#response-statusMessage" class="headerlink" title="response.statusMessage"></a>response.statusMessage</h3><ul>
<li><code><String></code></li>
</ul>
<p>为响应设置状态消息</p>
<pre><code class="javascript">// example
response.statusMessage = 'Not Found'
</code></pre>
<h3 id="resonse-write-chunk-encoding-callback"><a href="#resonse-write-chunk-encoding-callback" class="headerlink" title="resonse.write(chunk[, encoding][, callback]);"></a>resonse.write(chunk[, encoding][, callback]);</h3><ul>
<li><code>chunk<Buffer|String></code></li>
<li><code>encoding<String></code></li>
<li><code>callback<Function></code></li>
<li><code>Returns: <Boolean></code></li>
</ul>
<blockquote>
<p>If this method is called and <code>response.writeHead()</code> has not been called, it will switch to implicit header mode and flush the implicit headers.</p>
<p>The first time <code>response.write()</code> is called, it will send the buffered header information and the first body to the client. The second time response.write() is called, Node.js assumes you’re going to be streaming data, and sends that separately. That is, the response is buffered up to the first chunk of body.</p>
<p>Returns true if the entire data was flushed successfully to the kernel buffer. Returns false if all or part of the data was queued in user memory. ‘drain’ will be emitted when the buffer is free again.</p>
</blockquote>
<h3 id="response-writeHead-statusCode-statusMessage-headers"><a href="#response-writeHead-statusCode-statusMessage-headers" class="headerlink" title="response.writeHead(statusCode[, statusMessage][, headers])"></a>response.writeHead(statusCode[, statusMessage][, headers])</h3><ul>
<li><code>statusCode<Number></code></li>
<li><code>statusMessage<String></code></li>
<li><code>headers<Object></code></li>
</ul>
<p>response.writeHead会显式地在响应中设置头信息,在同一个response中writeHead方法只能调用一次, 且优先级高于<code>response.setHeader()</code>方法。<code>response.writeHead()</code>必须在<code>response.end()</code>方法之前调用。</p>
<blockquote>
<p>This method must only be called once on a message and it must be called before response.end() is called.</p>
</blockquote>
<h2 id="Class-http-IncomingMessage"><a href="#Class-http-IncomingMessage" class="headerlink" title="Class: http.IncomingMessage"></a>Class: http.IncomingMessage</h2><p><code>IncomingMessage</code>由http.Server或者http.ClientRequest创建,并且分别作为<code>request(http.Server)</code>和<code>response(http.clientRequest)</code>事件的第一个参数。实现了<a href="https://nodejs.org/dist/latest-v7.x/docs/api/stream.html#stream_class_stream_readable" target="_blank" rel="external">Readable Stream</a>接口。</p>
<h3 id="Event-‘aborted’-1"><a href="#Event-‘aborted’-1" class="headerlink" title="Event: ‘aborted’"></a>Event: ‘aborted’</h3><blockquote>
<p>Emitted when the request has been aborted by the client and the network socket has closed.</p>
</blockquote>
<h3 id="Event-‘close’-2"><a href="#Event-‘close’-2" class="headerlink" title="Event: ‘close’"></a>Event: ‘close’</h3><blockquote>
<p>Indicates that the underlying connection was closed. Just like ‘end’, this event occurs only once per response.</p>
</blockquote>
<h3 id="message-destroy-error"><a href="#message-destroy-error" class="headerlink" title="message.destroy([error])"></a>message.destroy([error])</h3><ul>
<li><code>error<Error></code></li>
</ul>
<p>在接收此message的socket上调用destroy方法。</p>
<h3 id="message-headers"><a href="#message-headers" class="headerlink" title="message.headers"></a>message.headers</h3><ul>
<li><code><Object></code></li>
</ul>
<p>请求头对象(key都是小写)。</p>
<h3 id="message-httpVersion"><a href="#message-httpVersion" class="headerlink" title="message.httpVersion"></a>message.httpVersion</h3><ul>
<li><code><String></code></li>
</ul>
<p>http版本</p>
<h3 id="message-method"><a href="#message-method" class="headerlink" title="message.method"></a>message.method</h3><ul>
<li><code><String></code></li>
</ul>
<blockquote>
<p>Only valid for request obtained from <code>http.Server</code>.</p>
</blockquote>
<h3 id="message-rawHeaders"><a href="#message-rawHeaders" class="headerlink" title="message.rawHeaders"></a>message.rawHeaders</h3><ul>
<li><code><Array></code></li>
</ul>
<p>rawHeaders把header的key和value放在同一个数组中。奇数位是key,偶数位是value。形式如下:</p>
<pre><code class="javascript">[ 'user-agent',
'this is invalid because there can be only one',
'User-Agent',
'curl/7.22.0',
'Host',
'127.0.0.1:8000',
'ACCEPT',
'*/*' ]
</code></pre>
<blockquote>
<p>Note that the keys and values are in the same list. It is not a list of tuples. So, the even-numbered offsets are key values, and the odd-numbered offsets are the associated values.</p>
<pre><code class="javascript">
</code></pre>
</blockquote>
<h3 id="message-rawTrailers-amp-message-trailers"><a href="#message-rawTrailers-amp-message-trailers" class="headerlink" title="message.rawTrailers & message.trailers"></a>message.rawTrailers & message.trailers</h3><ul>
<li><code><Array></code></li>
</ul>
<blockquote>
<p><code>rawTrailers</code> The raw request/response trailer keys and values exactly as they were received. Only populated at the ‘end’ event.</p>
<p><code>trailers</code> The request/response trailers object. Only populated at the ‘end’ event.</p>
</blockquote>
<h3 id="message-setTimeout-msecs-callback"><a href="#message-setTimeout-msecs-callback" class="headerlink" title="message.setTimeout(msecs, callback)"></a>message.setTimeout(msecs, callback)</h3><ul>
<li><code>msecs<Number></code></li>
<li><code>callback<Function></code></li>
</ul>
<blockquote>
<p>调用<code>message.connection.setTimeout(msecs, callback)</code>.</p>
</blockquote>
<h3 id="message-statusCode-amp-message-statusMessage"><a href="#message-statusCode-amp-message-statusMessage" class="headerlink" title="message.statusCode & message.statusMessage"></a>message.statusCode & message.statusMessage</h3><p>只有http.clientRequest的response事件处理程序中才有。</p>
<h3 id="message-socket"><a href="#message-socket" class="headerlink" title="message.socket"></a>message.socket</h3><p>返回该连接中的socket</p>
<h3 id="message-url"><a href="#message-url" class="headerlink" title="message.url"></a>message.url</h3><ul>
<li><code><String></code></li>
</ul>
<blockquote>
<p>Only valid for request obtained from http.Server.</p>
</blockquote>
<h2 id="http-createServer-requestListener"><a href="#http-createServer-requestListener" class="headerlink" title="http.createServer([requestListener])"></a>http.createServer([requestListener])</h2><ul>
<li>Returns <code><http.Server></code><br>返回一个新的http.Server的实例</li>
</ul>
<p>requestListener会自动添加到返回的<code>http.Server</code>的request事件上。</p>
<blockquote>
<p>The requestListener is a function which is automatically added to the <a href="https://nodejs.org/dist/latest-v7.x/docs/api/http.html#http_event_request" target="_blank" rel="external">request</a> event.</p>
</blockquote>
<h2 id="http-get-options-callback"><a href="#http-get-options-callback" class="headerlink" title="http.get(options[, callback])"></a>http.get(options[, callback])</h2><ul>
<li><code>options<Object></code></li>
<li><code>callback<Function></code></li>
<li>Returns <code><http.ClientRequest></code></li>
</ul>
<p>通常情况下get请求没有请求体,相比于<code>http.request</code>,<code>http.get</code>方法提供了一个比较便利的API,它们最主要的区别在于<code>http.get</code>将请求的method设置为了get,且自动调用了req.end()方法。</p>
<blockquote>
<p>Since most requests are GET requests without bodies, Node.js provides this convenience method. The only difference between this method and http.request() is that it sets the method to GET and calls req.end() automatically. Note that response data must be consumed in the callback for reasons stated in http.ClientRequest section.</p>
</blockquote>
<h2 id="http-globalAgent"><a href="#http-globalAgent" class="headerlink" title="http.globalAgent"></a>http.globalAgent</h2><ul>
<li><code><http.Agent></code></li>
</ul>
<blockquote>
<p>Global instance of Agent which is used as the default for all HTTP client requests.</p>
</blockquote>
<h2 id="http-request-options-callback"><a href="#http-request-options-callback" class="headerlink" title="http.request(options[, callback])"></a>http.request(options[, callback])</h2><ul>
<li><code>options<Object></code><ul>
<li><code>protocal<String></code> 默认’http’</li>
<li><code>host<String></code> 请求的域名或者IP,默认’localhost’</li>
<li><code>hostname<String></code> <code>host</code>的别称,优先级高于<code>host</code></li>
<li><code>family<Number></code> ip地址族,有效值是4或者6,默认情况是IPV4和IPV6都会使用。</li>
<li><code>port<Number></code> 请求的远程服务的端口,默认值:80</li>
<li><code>localAddress<String></code> Local interface to bind for network connections</li>
<li><code>socketPath<String></code> Unix的socket路径:<code>host:port</code></li>
<li><code>method<String></code> 请求的HTTP方法,默认使用’GET’</li>
<li><code>path<String></code> 请求路径,默认<code>/</code></li>
<li><code>headers<Object></code> 请求头</li>
<li><code>auth<String></code> Basic authentication</li>
<li><code>agent<http.Agent>|<Boolean></code> 控制Agent的行为</li>
<li><code>createConnection<Function></code> 当agent未设置时,此方法用于创建用于请求的<code>socket/stream</code></li>
<li><code>timeout<Number></code> 设置请求超时时间</li>
</ul>
</li>
<li><code>callback<Function></code> </li>
</ul>
<blockquote>
<p>The optional <code>callback</code> parameter will be added as a one time listener for the ‘response’ event.</p>
<p><code>http.request()</code> returns an instance of the http.ClientRequest class. The ClientRequest instance is a writable stream. If one needs to upload a file with a POST request, then write to the ClientRequest object.</p>
</blockquote>
<h1 id="References"><a href="#References" class="headerlink" title="References"></a>References</h1><ul>
<li><a href="https://nodejs.org/dist/latest-v7.x/docs/api/http.html" target="_blank" rel="external">Node.js - HTTP</a></li>
<li><a href="https://nodejs.org/en/docs/guides/anatomy-of-an-http-transaction/" target="_blank" rel="external">Anatomy of an Http Transaction</a></li>
</ul>
]]></content>
</entry>
<entry>
<title><![CDATA[Node.js学习笔记 - process]]></title>
<url>http://blog.dzyhenry.com/2016/12/08/process/</url>
<content type="html"><![CDATA[<h2 id="Process"><a href="#Process" class="headerlink" title="Process"></a>Process</h2><p>The process object is a global that provides information about, and control over, the current Node.js process. As a global, it is always available to Node.js applications without using require().</p>
<a id="more"></a>
<h2 id="Events"><a href="#Events" class="headerlink" title="Events"></a>Events</h2><h3 id="Event-‘beforeExit’-beforeExit事件会在Node的event-loop队列为空的时候触发,此时Node的event-loop并未终止,也就意味着事件处理程序可以进行异步操作。"><a href="#Event-‘beforeExit’-beforeExit事件会在Node的event-loop队列为空的时候触发,此时Node的event-loop并未终止,也就意味着事件处理程序可以进行异步操作。" class="headerlink" title="Event: ‘beforeExit’ - beforeExit事件会在Node的event loop队列为空的时候触发,此时Node的event loop并未终止,也就意味着事件处理程序可以进行异步操作。"></a>Event: ‘beforeExit’ - <code>beforeExit</code>事件会在Node的event loop队列为空的时候触发,此时Node的<code>event loop</code>并未终止,也就意味着事件处理程序可以进行异步操作。</h3><ul>
<li>如果process显示终止(譬如:<code>process.exit()</code>, <code>uncaught exception</code>),<code>beforeExit</code>事件不会触发。</li>
</ul>
<h3 id="Event-‘exit’"><a href="#Event-‘exit’" class="headerlink" title="Event: ‘exit’"></a>Event: ‘exit’</h3><ul>
<li><code>process.exit()</code> 调用时触发;</li>
<li><code>exit</code>事件在<code>event loop</code>队列为空时候触发</li>
<li>事件监听程序只能处理同步代码。</li>
</ul>
<p>下面这段代码可以清晰地反应这两个事件的区别</p>
<pre><code class="javascript">// 不会输出'exit setTimeout'
process.on('exit', (code) => {
console.log(`About to exit, the exit code is ${code}`);
setTimeout(() => {
console.log('exit setTimeout');
}, 1000);
});
// 会每隔一秒地输出‘beforeExit setTimeout’
process.on('beforeExit', (code) => {
console.log(`About to exit, the exit code is ${code}`);
setTimeout(() => {
console.log('beforeExit setTimeout');
}, 1000);
});
</code></pre>
<p>所以,<code>exit</code>事件触发后,进程的<code>event loop</code>不会再接受新的代码执行,而<code>beforeExit</code>事件触发以后,event loop能够继续正常的工作。</p>
<h3 id="Event-‘uncaughtException’"><a href="#Event-‘uncaughtException’" class="headerlink" title="Event: ‘uncaughtException’"></a>Event: ‘uncaughtException’</h3><p>当JavaScript代码执行过程中出现未捕获的异常,并传递到<code>event loop</code>中时,<code>uncaughtException</code>事件就会触发。</p>
<p>通常来讲,<code>uncaughtException</code>事件触发以后,其事件监听程序应当是程序在真正退出之前执行的最后一段代码,所以<code>uncaughtException</code>事件监听程序的应当用来做释放资源之类的工作。但是,结合前面的两个事件<code>beforeExit</code>,<code>exit</code>,我们会发现一个有趣的现象。</p>
<pre><code class="javascript">process.on('beforeExit', () => {
console.log('before exit');
setTimeout(() => {
console.log(bk);
}, 1000);
});
setTimeout(() => {
console.log('This will still run.');
}, 500);
// Intentionally cause an exception, but don't catch it.
nonexistentFunc();
console.log('This will not run.');
</code></pre>
<p>上面的代码中,<code>beforeExit</code>事件不会触发,原因很简单,当程序通过<code>process.exit()</code>或者遇到<code>uncaughtException</code>退出的时候,<code>beforeExit</code>并不会触发。但是,请看看下面的代码:</p>
<pre><code class="javascript">process.on('uncaughtException', (err) => {
console.log('uncaughtException', err);
});
process.on('beforeExit', () => {
console.log('before exit');
setTimeout(() => {
console.log(bk);
}, 1000);
});
setTimeout(() => {
console.log('This will still run.');
}, 500);
// Intentionally cause an exception, but don't catch it.
nonexistentFunc();
console.log('This will not run.');
</code></pre>
<p>如果你把代码执行一下就会发现,当<code>uncaughtException</code>的事件监听程序被执行以后,后续<code>event loop</code>会继续工作。但正如<a href="https://nodejs.org/dist/latest-v7.x/docs/api/process.html#process_event_uncaughtexception" target="_blank" rel="external">文档</a>上所描述的,试图在异常未捕获的情况下,继续正常执行代码,正如在计算机升级的时候突然拔掉电源,总会有机会使得系统崩溃。所以,在实际应用场景中,我们应当确保<code>uncaughtException</code>的事件监听程序应当是当前process执行的最后一段代码。</p>
<blockquote>
<p>Attempting to resume normally after an uncaught exception can be similar to pulling out of the power cord when upgrading a computer – nine out of ten times nothing happens - but the 10th time, the system becomes corrupted. –<a href="https://nodejs.org/dist/latest-v7.x/docs/api/process.html#process_warning_using_uncaughtexception_correctly" target="_blank" rel="external">process</a></p>
</blockquote>
<h3 id="Signal-Events"><a href="#Signal-Events" class="headerlink" title="Signal Events"></a><a href="https://nodejs.org/dist/latest-v7.x/docs/api/process.html#process_signal_events" target="_blank" rel="external">Signal Events</a></h3><p>当Node.js进程接收到signal时会触发相应的Signal Events</p>
<h4 id="SIGTERM-amp-SIGINT"><a href="#SIGTERM-amp-SIGINT" class="headerlink" title="SIGTERM & SIGINT"></a>SIGTERM & SIGINT</h4><p>在Node.js的进程中,可以设置<code>SIGTERM</code>和<code>SIGINT</code>的listener,同时会阻止默认行为。<br>关于<code>SIGINT</code>这个命令在非windows平台可以通过下面这段代码模拟。在终端里面启动Node.js进程以后,通过<code>$Control-C</code>会给进程发送<code>SIGTERM</code>信号,<code>$kill pid</code>会发送<code>SIGINT</code>信号。</p>
<pre><code class="javascript">// Try press Control-C, which will send a SINGINT signal to the process.
process.stdin.resume();
// The diffrence between Control-C and Control-D
// http://superuser.com/questions/169051/whats-the-difference-between-c-and-d-for-unix-mac-os-x-terminal
process.on('SIGINT', () => {
console.log('Received SIGINT. Press Control-D to exit');
});
</code></pre>
<blockquote>
<p>SIGTERM and SIGINT have default handlers on non-Windows platforms that resets the terminal mode before exiting with code 128 + signal number. If one of these signals has a listener installed, its default behavior will be removed (Node.js will no longer exit).</p>
</blockquote>
<p>所以在Node.js的http server进程中,如果正在处理某个请求的server进程接收到<code>SIGINT</code>或<code>SIGTERM</code>信号时,我们可以考虑让server处理完这个请求,并且拒绝接下来的请求,然后以一种更优雅的方式关闭。这里有一个方案,来自<a href="http://joseoncode.com/2014/07/21/graceful-shutdown-in-node-dot-js/" target="_blank" rel="external">Graceful shutdown in Node.js</a>:</p>
<pre><code class="javascript">var http = require('http');
var server = http.createServer(function (req, res) {
setTimeout(function () { //simulate a long request
res.writeHead(200, {'Content-Type': 'text/plain'});
res.end('Hello World\n');
}, 4000);
}).listen(9090, function (err) {
console.log('listening http://localhost:9090/');
console.log('pid is ' + process.pid);
});
// Graceful shut down: listen to SIGTERM, excute server.close(). Close the server after processing the last hanging request.
process.on('SIGTERM', function () {
server.close(function () {
process.exit(0);
});
});
</code></pre>
<h4 id="SIGKILL"><a href="#SIGKILL" class="headerlink" title="SIGKILL"></a>SIGKILL</h4><p>在所有平台上,Node.js进程在接收到<code>SIGKILL</code>信号时会无条件的结束进程。</p>
<blockquote>
<p>SIGKILL cannot have a listener installed, it will unconditionally terminate Node.js on all platforms.</p>
</blockquote>
<h2 id="porcess-abort"><a href="#porcess-abort" class="headerlink" title="porcess.abort"></a>porcess.abort</h2><p>进程立即退出,并生成<a href="https://en.wikipedia.org/wiki/Core_dump" target="_blank" rel="external">core file</a>。</p>
<blockquote>
<p>The process.abort() method causes the Node.js process to exit immediately and generate a core file.</p>
</blockquote>
<h2 id="process-arch-process-platform"><a href="#process-arch-process-platform" class="headerlink" title="process.arch, process.platform"></a>process.arch, process.platform</h2><ul>
<li>process.arch: 返回运行Node.js进程的处理器架构,譬如<code>arm</code>, <code>ia32</code>, <code>x64</code></li>
<li>process.platform: 返回运行Node.js进程的操作系统平台,譬如 <code>linux</code>, <code>windows</code>, <code>darwin</code>, <code>freebsd</code></li>
</ul>
<h2 id="process-env-process-argv-process-execArgv"><a href="#process-env-process-argv-process-execArgv" class="headerlink" title="process.env, process.argv, process.execArgv"></a>process.env, process.argv, process.execArgv</h2><ol>
<li>添加的环境变量:process.env应该在node命令之前,譬如</li>
</ol>
<pre><code class="bash">NODE_ENV=production node worker.js
</code></pre>
<p>如果写成下面这样,process.env不会有NODE_ENV,参数会被加在process.argv当中。</p>
<pre><code class="bash">node worker.js NODE_ENV=production
process.argv returns: ['node', 'worker.js', 'NODE_ENV=production']
</code></pre>
<ol>
<li>process.execArgv: 返回Node.js进程启动的时候,Node.js的命令行选项。例如:</li>
</ol>
<pre><code class="bash">node --harmony script.js --version
# process.execArgv returns ['--harmony']
</code></pre>
<blockquote>
<p>The process.execArgv property returns the set of Node.js-specific command-line options passed when the Node.js process was launched. </p>
</blockquote>
<ol>
<li><strong>赋给<code>process.env</code>的值会隐式地转换为<code>String</code>类型。</strong></li>
</ol>
<h2 id="process-execPath-procee-cwd"><a href="#process-execPath-procee-cwd" class="headerlink" title="process.execPath, procee.cwd()"></a>process.execPath, procee.cwd()</h2><ol>
<li><code>process.execPath</code>:返回启动Node.js进程的程序的绝对路径</li>
<li><code>process.cwd()</code>:返回当前Node.js进程启动的绝对路径</li>
</ol>
<pre><code class="javascript">console.log(process.cwd());
// returns '/Users/henry/demos/node'
console.log(process.execPah);
// returns '/Users/henry/.nvm/versions/node/v7.0.0/bin/node'
</code></pre>
<h2 id="process-exit-code-process-exitCode"><a href="#process-exit-code-process-exitCode" class="headerlink" title="process.exit([code]), process.exitCode"></a>process.exit([code]), process.exitCode</h2><ol>
<li><code>process.exit()</code>会使进程强制退出,“挂起”的异步操作会被丢弃。</li>
<li><code>process.exitCode</code>,为默认情况下的Node.js进程退出设置退出码。</li>
</ol>
<h2 id="process-hrtime"><a href="#process-hrtime" class="headerlink" title="process.hrtime()"></a>process.hrtime()</h2><p>返回<code>[second, nanoseconds]</code>的高精度时间元组,可以传入一个process.hrtime()返回值的参数,返回两个时间元组之间的时间差。process.hrtime()可以用来做高精度的性能评估。</p>
<pre><code class="javascript">const time = process.hrtime();
setTimeout(() => {
const diff = process.hrtime(time);
console.log(`Benchmark took ${(diff[0] * 1e9) + diff[1]} nanoseconds`);
// benchmark took 1000000527 nanoseconds
}, 1000);
</code></pre>
<h2 id="process-kill-pid-signal"><a href="#process-kill-pid-signal" class="headerlink" title="process.kill(pid, [signal])"></a>process.kill(pid, [signal])</h2><p>给指定的<code>processid</code>发送一个信号,默认信号时<code>SIGTERM</code>。</p>
<p><strong>注:</strong> 此API虽然叫做<code>kill</code>,但其功能仅仅是给指定的进程发送信号,且默认发送的信号是:<code>SINGTERM</code>。</p>
<blockquote>
<p>Note:Even though the name of this function is process.kill(), it is really just a signal sender, like the kill system call. The signal sent may do something other than kill the target process.</p>
</blockquote>
<h2 id="process-mainModule"><a href="#process-mainModule" class="headerlink" title="process.mainModule"></a>process.mainModule</h2><ul>
<li>相比于<code>require.main</code>, <code>process.mainModule</code>提供了一种新的方法获取当前主模块。</li>
<li>与<code>require.main</code>不同的是,<code>require.main</code>在代码执行阶段会改变,而process.main的值则一直是Node.js进程启动时的最初模块。</li>
</ul>
<h2 id="process-memoryUsage"><a href="#process-memoryUsage" class="headerlink" title="process.memoryUsage()"></a>process.memoryUsage()</h2><p>返回当前Node.js进程内存使用情况的object,内存单位是Byte。</p>
<pre><code class="javascript">const util = require('util');
console.log(util.inspect(process.memoryUsage()));
// prints: { rss: 21262336, heapTotal: 10465280, heapUsed: 4396160 }
</code></pre>
<h2 id="process-nextTick"><a href="#process-nextTick" class="headerlink" title="process.nextTick()"></a>process.nextTick()</h2><p>在解释<code>process.nextTick()</code>之前, 有必要先了解一下Node.js中的<code>Event loop</code>是如何工作的,详情可参照<a href="https://github.com/nodejs/node/blob/master/doc/topics/event-loop-timers-and-nexttick.md" target="_blank" rel="external">官网解释</a>。</p>
<p>下图是Node.js简化版的Event loop,来自<a href="https://github.com/nodejs/node/blob/master/doc/topics/event-loop-timers-and-nexttick.md#poll" target="_blank" rel="external">Node.js的官方文档</a>。</p>
<pre><code> ┌───────────────────────┐
┌─&gt;│ timers │
│ └──────────┬────────────┘
│ ┌──────────┴────────────┐
│ │ I/O callbacks │
│ └──────────┬────────────┘
│ ┌──────────┴────────────┐
│ │ idle, prepare │
│ └──────────┬────────────┘ ┌───────────────┐
│ ┌──────────┴────────────┐ │ incoming: │
│ │ poll │&lt;─────┤ connections, │
│ └──────────┬────────────┘ │ data, etc. │
│ ┌──────────┴────────────┐ └───────────────┘
│ │ check │
│ └──────────┬────────────┘
│ ┌──────────┴────────────┐
└──┤ close callbacks │
└───────────────────────┘
</code></pre><blockquote>
<p>Each phase has a FIFO queue of callbacks to execute. While each phase is special in its own way, generally, when the event loop enters a given phase, it will perform any operations specific to that phase, then execute callbacks in that phase’s queue until the queue has been exhausted or the maximum number of callbacks has executed. When the queue has been exhausted or the callback limit is reached, the event loop will move to the next phase, and so on.</p>
</blockquote>
<p>图中的每一个矩形代码Node.js的Event loop的每一个阶段(Phase)。值得一说的是,Node.js的Event loop模型和我们通常理解的浏览器的Event loop是有区别的,主要区别是Node.js对于不同的异步操作类型有不同的处理步骤和方式。具体如下:</p>
<ul>
<li><strong>timers</strong>: this phase excutes callbacks scheduled by <code>setTimeout()</code> and <code>setInterval()</code>.</li>
<li><strong>I/O callbacks</strong>: excutes almost all callbacks with the exception of close callbacks, the ones scheduled by timers.</li>
<li><strong>idle, prepare</strong>: only used internaly.</li>
<li><strong>poll</strong>: retrieve new I/O events, node will block here when appropriate.</li>
<li><strong>check</strong>: <code>setImmediate()</code> callbacks are invoked here.</li>
<li><strong>close callbacks</strong>: e.g. <code>socket.on('close', ...)</code>.</li>
</ul>
<h3 id="setImmediate-vs-setTimeout"><a href="#setImmediate-vs-setTimeout" class="headerlink" title="setImmediate vs. setTimeout"></a>setImmediate vs. setTimeout</h3><p>下面的代码,如果处于Node.js进程执行的主模块中,<code>setTimeout</code>和<code>setImmediate</code>的执行顺序是不确定的。</p>
<pre><code class="javascript">setTimeout(() => {
console.log('setTimeout');
}, 0);
setImmediate(() => {
console.log('setImmediate');
});
</code></pre>
<p>由于<code>setTimeout</code>的callback执行是在timers阶段,<code>setImmediate</code>的执行在check阶段,所以<code>setTimeout</code>和<code>setImmediate</code>的执行顺序会依赖于当前process所处的Event loop阶段。</p>
<blockquote>
<p>setImmediate and setTimeout() are similar, but behave in different ways depending on when they are called.</p>
<ul>
<li>setImmediate() is designed to execute a script once the current poll phase completes.</li>
<li>setTimeout() schedules a script to be run after a minimum threshold in ms has elapsed.</li>
</ul>
<p>The order in which the timers are executed will vary depending on the context in which they are called. If both are called from within the main module, then timing will be bound by the performance of the process (which can be impacted by other applications running on the machine).</p>
</blockquote>
<h3 id="process-nextTick-1"><a href="#process-nextTick-1" class="headerlink" title="process.nextTick()"></a>process.nextTick()</h3><p>严格来讲,process.nextTick不处于<code>Event loop</code>的任何阶段。<code>nextTickQueue</code>(<code>process.nextTick</code>的回调队列)会在当前操作(当前phase的执行)执行结束以后执行。 </p>
<blockquote>
<p>This is important when developing APIs in order to give users the opportunity to assign event handlers after an object has been constructed but before any I/O has occurred:</p>
</blockquote>
<p>根据本节开始处的Event loop示意图。当我们在构造对象后想要理解做一些事情,并且这些事情需要在所有I/O回调执行之前执行时,就有必要使用<code>process.nextTick()</code>,这也是<code>process.nextTick()</code>的用武之地之一。</p>
<pre><code class="javascript">function MyThing(options) {
this.setupOptions(options);
process.nextTick(() => {
this.startDoingStuff();
});
}
var thing = new MyThing();
thing.getReadyForStuff();
</code></pre>
<p>对于<code>process.nextTick()</code>需要注意的是:由于<code>process.nextTick()</code>会在<code>Event loop</code>的任意phase结束后立即执行,递归调用<code>process.nextTick()</code>会阻塞<code>Event loop</code>中的I/O调用。</p>
<h2 id="process-stdin-process-stdout-process-stderr"><a href="#process-stdin-process-stdout-process-stderr" class="headerlink" title="process.stdin, process.stdout, process.stderr"></a>process.stdin, process.stdout, process.stderr</h2><ul>
<li><code>process.stdin</code>返回一个与<code>stdin(fd 0)</code>一致或者相关联<code>Readable stream</code>。</li>
<li><code>process.stdout</code>返回一个与<code>stdout(fd 1)</code>一致或相关联的<code>Writable stream</code>。</li>
<li><code>process.stderr</code>返回一个与<code>stderr(fd 2)</code>一致或相关联的<code>Writable stream</code>。</li>
</ul>
<p>关于<code>process.stderr</code>与<code>process.stdout</code>的区别主要有以下几点:</p>
<ol>
<li><code>process.stderr</code>不能被<code>close</code>(<code>end()</code>会抛出异常)</li>
<li><code>process.stderr</code>不会触发<code>finish</code>事件</li>
<li><code>process.stderr</code>当输出至文件时,write将会阻塞</li>
<li><code>process.stdout</code>和<code>process.stderr</code>在Unix平台上,当输出到TTY(Terminal)时,write将会被阻塞</li>
<li><code>process.stdout</code>和<code>process.stderr</code>在Windows平台上,对于第4点,恰好相反</li>
</ol>
<h2 id="TTY-Terminals"><a href="#TTY-Terminals" class="headerlink" title="TTY Terminals"></a>TTY Terminals</h2><p>关于什么是tty,<a href="http://unix.stackexchange.com/questions/4126/what-is-the-exact-difference-between-a-terminal-a-shell-a-tty-and-a-con" target="_blank" rel="external">这里</a>有一篇科普文。</p>
<p><code>process.stdout</code>和<code>process.stderr</code>在UNIX平台上当输出至TTYs(Terminals)时是阻塞的,所以可以有效防止<code>stdout</code>和<code>stderr</code>之间的相互干扰。<br>所以有如下方法可以检查Node.js是否在TTY的上下文中运行。</p>
<pre><code class="bash">$ node -p "Boolean(process.stdin.isTTY)"
true
$ echo "foo" | node -p "Boolean(process.stdin.isTTY)"
false
$ node -p "Boolean(process.stdout.isTTY)"
true
$ node -p "Boolean(process.stdout.isTTY)" | cat
false
</code></pre>
<h2 id="process-uptime"><a href="#process-uptime" class="headerlink" title="process.uptime()"></a>process.uptime()</h2><p>返回当前Node.js进程所运行的时间</p>
<h2 id="Reference"><a href="#Reference" class="headerlink" title="Reference"></a>Reference</h2><ul>
<li><a href="https://nodejs.org/dist/latest-v7.x/docs/api/process.html" target="_blank" rel="external">Node.js v7.1.0 Documentation</a></li>
<li><a href="http://unix.stackexchange.com/questions/76634/what-is-a-process-gid-and-what-purpose-does-it-serve" target="_blank" rel="external">What is a process GID and what purpose does it serve?</a></li>
<li><a href="https://hackernoon.com/19-things-i-learnt-reading-the-nodejs-docs-8a2dcc7f307f#.exxn0rqoe" target="_blank" rel="external">19 things I’ve learnt from the Node.js Docs</a></li>
<li><a href="https://github.com/nodejs/node/blob/master/doc/topics/event-loop-timers-and-nexttick.md" target="_blank" rel="external">The Node.js Event Loop, Timers, and process.nextTick()</a></li>
<li><a href="https://segmentfault.com/a/1190000003063859" target="_blank" rel="external">Linux IO模式及 select、poll、epoll详解</a></li>
<li><a href="http://unix.stackexchange.com/questions/4126/what-is-the-exact-difference-between-a-terminal-a-shell-a-tty-and-a-con" target="_blank" rel="external">What is the exat difference between a ‘terminal’, a ‘shell’, a ‘tty’ and a ‘console’</a></li>
</ul>
]]></content>
</entry>
<entry>
<title><![CDATA[IScroll使用指南]]></title>
<url>http://blog.dzyhenry.com/2016/09/10/iscroll_guide/</url>
<content type="html"><![CDATA[<p>IScroll最核心的功能就是通过JavaScript控制元素的位移来实现有关滑动的各种需求。其主要工作方式是通过监听DOM事件,改变滑动元素的CSS属性值来实现元素的位移,同时做了大量浏览器的兼容性处理。</p>
<p>当我们在进行移动端开发的时候,难免会遇到需要通过代码来控制元素滑动的场景,比如滑动列表的“下拉刷新”功能、日历或轮播组件的“snap功能”,这个时候IScroll就可以作为一个提高我们开发效率的利器。<br><a id="more"></a><br>本文主要简单介绍一下IScroll工作的原理,帮助大家更好地使用IScroll。<br>具体的API接口和使用可以参考<a href="http://iscrolljs.com/" target="_blank" rel="external">IScroll官方文档</a></p>
<h2 id="IScroll代码简单分析"><a href="#IScroll代码简单分析" class="headerlink" title="IScroll代码简单分析"></a>IScroll代码简单分析</h2><h3 id="DOM事件的注册"><a href="#DOM事件的注册" class="headerlink" title="DOM事件的注册"></a>DOM事件的注册</h3><p>IScroll在初始化阶段就通过<code>_initEvent</code>方法注册了需要处理的DOM事件。IScroll对象实现了<a href="https://www.w3.org/TR/DOM-Level-2-Events/events.html#Events-EventListener" target="_blank" rel="external">EventListener</a>接口,监听<code>touchstart</code>, <code>touchmove</code>, <code>touchend</code>等事件,作为用户交互的事件基础。下面是IScroll HandleEvent的部分代码,我们可以看到IScroll最核新的<code>Event Handler</code>就是<code>_start</code>,<code>_move</code>, <code>_end</code>,:</p>
<pre><code class="javascript">handleEvent: function (e) {
switch ( e.type ) {
case 'touchstart':
case 'mousedown':
//...兼容事件
this._start(e);
break;
case 'touchmove':
case 'mousemove':
//...兼容事件
this._move(e);
break;
case 'touchend':
case 'mouseup':
//...兼容事件
this._end(e);
break;
case 'click':
// 注:IScroll默认会阻止click事件的默认行为和冒泡,会影响react的click事件,
// 我们可以在初始化时设置options: { click: true },让click事件得以触发
if ( this.enabled && !e._constructed ) {
e.preventDefault();
e.stopPropagation();
}
break;
}
}
</code></pre>
<h3 id="自定义事件"><a href="#自定义事件" class="headerlink" title="自定义事件"></a>自定义事件</h3><p>在处理浏览器事件的同时,IScroll也实现了自定义事件系统,目的是给用户提供一些Hook,方便处理滑动过程前、中、后以及刷新,销毁等事件,譬如: <code>beforeScrollStart</code>, <code>scrollStart</code>, <code>scrollEnd</code>,<code>destroy</code>,<code>scrollCancel</code>, <code>flick</code>, <code>refresh</code>等。</p>
<p>下面的代码是IScroll自定义事件系统调用<code>Event Handler</code>代码,相当于DOM自定义事件的dispatch方法。</p>
<pre><code class="javascript">_execEvent: function (type) {
if ( !this._events[type] ) {
return;
}
var i = 0,
l = this._events[type].length;
if ( !l ) {
return;
}
for ( ; i < l; i++ ) {
this._events[type][i].apply(this, [].slice.call(arguments, 1));
}
}
</code></pre>
<p>从下面的代码我们也可以看到,<code>beforeScrollStart</code>和<code>scrollEnd</code>事件会在<code>_start</code> handler的某个时机调用</p>
<pre><code class="javascript"> _start: function (e) {
// some other code
if ( this.options.useTransition && this.isInTransition ) {
this._transitionTime();
this.isInTransition = false;
pos = this.getComputedPosition();
this._translate(Math.round(pos.x), Math.round(pos.y));
this._execEvent('scrollEnd');
} else if ( !this.options.useTransition && this.isAnimating ) {
this.isAnimating = false;
this._execEvent('scrollEnd');
}
// ...some other code
this._execEvent('beforeScrollStart');
}
</code></pre>
<h3 id="位移的实现"><a href="#位移的实现" class="headerlink" title="位移的实现"></a>位移的实现</h3><p>IScroll中提供了两种位移的方式,都是通过控制滑动元素的CSS样式来实现。</p>
<ol>
<li>当<code>useTransform</code>为false或者检测到浏览器不支持<code>transform</code>属性时,使用<code>position+top+left</code>的方式实现位移。</li>
<li>当<code>useTransform</code>为true【默认】且浏览器支持<code>transform</code>属性时,使用<code>transform+translate</code>实现位移</li>
</ol>
<p>位移最终会封装成IScroll的prototype属性上的<code>_translate</code>方法</p>
<pre><code class="javascript">_translate: function (x, y) {
if ( this.options.useTransform ) {
this.scrollerStyle[utils.style.transform] = 'translate(' + x + 'px,' + y + 'px)' + this.translateZ; // 使用transform属性的方式
} else {
// 使用定位的方式
x = Math.round(x);
y = Math.round(y);
this.scrollerStyle.left = x + 'px';
this.scrollerStyle.top = y + 'px';
}
this.x = x; // 更新坐标
this.y = y;
},
</code></pre>
<p>并且暴露给用户的<code>scrollTo</code>, <code>scrollToElement</code>API也依赖于<code>_translate</code>方法。</p>
<pre><code class="javascript">scrollTo: function (x, y, time, easing) {
easing = easing || utils.ease.circular;
this.isInTransition = this.options.useTransition && time > 0;
var transitionType = this.options.useTransition && easing.style;
if ( !time || transitionType ) {
if(transitionType) {
this._transitionTimingFunction(easing.style);
this._transitionTime(time);
}
this._translate(x, y);
} else {
this._animate(x, y, time, easing.fn); // _animate也依赖于_translate
}
}
</code></pre>
<h3 id="位移中的动画实现"><a href="#位移中的动画实现" class="headerlink" title="位移中的动画实现"></a>位移中的动画实现</h3><p>对于滑动元素滑动中的动画,为了兼容性处理,iscroll同样提供了两种方式:</p>
<ol>
<li>当useTransition为false或者检测到浏览器不支持transition时,采用<a href="http://www.paulirish.com/2011/requestanimationframe-for-smart-animating/" target="_blank" rel="external">requestAnimationFrame</a>的回调来模拟位移,如果requestAnimationFrame也不支持的话,就采用<code>setTimeout(() => _transition(), 1000/60)</code>来模拟一帧一帧的位移。</li>
<li>当useTransition为true,且浏览器支持transition属性,则直接使用<code>_translate</code>方法实现位移即可,滑动的动画依靠浏览器自身实现。</li>
</ol>
<p>IScroll会计算每次滑动动作的开始时间和结束时间,并计算滑动速度,计算滑动动量,使滑动变得更加顺畅。</p>
<h3 id="一些常见的API或者属性"><a href="#一些常见的API或者属性" class="headerlink" title="一些常见的API或者属性"></a>一些常见的API或者属性</h3><ol>
<li><code>maxScrollY, maxScrollX</code>: IScroll在初始化时会计算滑动元素(Scroller,后面统称Scroller)以及其容器(Scroll Wrapper,后面统称Scroll Wrapper)的高度和宽度,maxScrollY和maxScrollx代表的就是可以滑动的最大距离。</li>
</ol>
<pre><code class="javascript">maxScrollY = (Scroll Wrapper).clientHeight - Scroller.clientHeight
maxScrollX = (Scroll Wrapper).clientWidth - Scroller.clientWidth
</code></pre>
<p>所以maxScrollX和maxScrollY都是小于等于0的。</p>
<ol>
<li><code>y, x</code>, 分别指当前Scroller滑动的垂直距离和水平距离,初始值都是0。</li>
<li>通常情况下,当<code>y < maxScrollY</code>时,当<code>touchend</code>的<code>event handler</code>会将Scroller恢复到<code>y=maxScrollY</code>的距离,<code>y >0</code>时,Scroller也会恢复到<code>y=0</code>的位置(水平方向的<code>x</code>同理)。</li>
<li><code>scrollTo(x, y, time)</code>,控制Scroller滑动到某个位置。</li>
<li><code>refresh</code>,重新计算maxScrollX,maxScrollY等参数。</li>
</ol>
<h3 id="一些常见的使用场景"><a href="#一些常见的使用场景" class="headerlink" title="一些常见的使用场景"></a>一些常见的使用场景</h3><ol>
<li><p>如何扩大滑块的滑动距离?<br>改变<code>maxScrollY</code>和<code>maxScrollX</code>即可。</p>
</li>
<li><p>当Scroller的高度(宽度)小于Scroll Wrapper的高度(宽度)时,默认情况下,Scroller是无法滑动的,那么怎么让它又可以滑动呢?<br>设置<code>hasVerticalScrol</code>和<code>hasHorizontalScroll</code>为<code>true</code>即可</p>
</li>
<li><p>从新计算maxScrollY和maxScrollX,调用<code>refresh</code>即可</p>
</li>
</ol>
]]></content>
</entry>
<entry>
<title><![CDATA[Excerpt]]></title>
<url>http://blog.dzyhenry.com/2016/08/21/understanding_the_difference_jit_aot/</url>
<content type="html"><![CDATA[<h2 id="Interpreter"><a href="#Interpreter" class="headerlink" title="Interpreter"></a>Interpreter</h2><blockquote>
<p>In computer science, an interpreter is a computer program that directly executes, i.e. performs, instructions written in a programming or scripting language, without previously compiling them into a machine language program. An interpreter generally uses one of the following strategies for program execution:<br><a id="more"></a></p>
</blockquote>
<ol>
<li>parse the source code and perform its behavior directly.</li>
<li>translate source code into some efficient intermediate representation and immediately execute this.</li>
<li>explicitly execute stored precompiled code made by a compiler which is part of the interpreter system.<br>—–<a href="https://en.wikipedia.org/wiki/Interpreter_(computing" target="_blank" rel="external">Interpreter (computing)</a>)</li>
</ol>
<p>An interpreter for language <strong>X</strong> is a program(or a machine, or just some kind of mechanism in general)that <strong>excutes</strong> any program <strong>P</strong> written in language <strong>X</strong> such that is performs the effects and evaluates the results as prescribed by the specification of <strong>X</strong>.</p>
<h2 id="Compiler"><a href="#Compiler" class="headerlink" title="Compiler"></a>Compiler</h2><p>A compiler from <strong>X</strong> to <strong>Y</strong> is a program(or a machine, or just some kine of mechanism in general)that translates any program <strong>p</strong> from some language <strong>X</strong> into a semantically equivalent program p’ in some language <strong>Y</strong> in such a way that the semantics of the program are preserved, i.e. that interpreting p’ with an interpreter for <strong>Y</strong> will yield the same results and have the same effects as interpreting <strong>p</strong> with an interpreter for <strong>X</strong>.(Note that <strong>X</strong> and <strong>Y</strong> may be the same language.)</p>
<h2 id="Ahead-of-Time-AOT-amp-amp-Just-in-Time-JIT"><a href="#Ahead-of-Time-AOT-amp-amp-Just-in-Time-JIT" class="headerlink" title="Ahead-of-Time(AOT) && Just-in-Time(JIT)"></a>Ahead-of-Time(AOT) && Just-in-Time(JIT)</h2><p>The terms Ahead-of-Time(AOT) and Just-in-Time(JIT) refer to when compilation take place: the “time” reffered to in those terms is “runtime”, i.e. a JIT compiler compiles the program as it is running, an AOT compiler compiles the program before it is running. Note that this requires that a JIT compiler from language <strong>X</strong> to language <strong>Y</strong> must somehow work together with an interpreter for language <strong>Y</strong>, otherwise there wouldn’t be any way to run the program.</p>
<p>Note that this distinction doesn’t make sense for interpreters: an interpreter runs the program, the idea of an AOT interpreter that runs a programming before it is running or a JIT interpreter that runs a program while it is running is nonsensical.</p>
<p>So, we have<br><strong>AOT compiler: compiles before running</strong><br><strong>JIT compiler: compiles while running</strong><br><strong>interpreter: runs</strong></p>
<p>Interpreters and compilers may be combined into a single language execution engine. There are two typical scenarios where this is done.</p>
<h3 id="1-First-Scenario"><a href="#1-First-Scenario" class="headerlink" title="1 First Scenario"></a>1 First Scenario</h3><p>Combining an AOT compiler from X to Y with an interpreter for Y. Here, typically X is some higher-level language optimized for readability by humans, whereas Y is a compact language (often some kind of bytecode) optimized for interpretability by machines. </p>
<h3 id="2-Second-Scenario"><a href="#2-Second-Scenario" class="headerlink" title="2 Second Scenario"></a>2 Second Scenario</h3><p>The other way to combine an interpreter and a compiler is a mixed-mode execution engine. Here, we “mix” two “modes” of implementing the same language together, i.e. an interpreter for X and a JIT compiler from X to Y. Code that has been compiled by a compiler tends to run faster than code that is executed by an interpreter, but actually compiling the code first takes time. So, to bridge this time where the JIT compiler is busy compiling the code, the interpreter can already start running the code, and once the JIT is finished compiling, we can switch execution over to the compiled code. </p>
<p>More interesting possibilities are, for example, to not start compiling right away, but let the interpreter run for a bit, and collect statistics, profiling information, type information, information about the likelihood of which specific conditional branches are taken, which methods are called most often etc. and then feed this dynamic information to the compiler so that it can generate more optimized code.<br>It is also possible and in fact common to combine those two approaches: two phases with the first being an AOT compiler that compiles X to Y and the second phase being a mixed-mode engine that both interprets Y and compiles Y to Z. <strong>The Rubinius Ruby execution engine works this way.</strong></p>
<p>Note that the role that the interpreter plays in the case of a mixed-mode execution engine, namely providing fast startup, and also potentially collecting information and providing fallback capability may alternatively also be played by a second JIT compiler. This is how V8 works, for example. <strong>V8 never interprets, it always compiles.</strong> The first compiler is a very fast, very slim compiler that starts up very quick. The code it produces isn’t very fast, though. This compiler also injects profiling code into the code it generates. The other compiler is slower and uses more memory, but produces much faster code, and it can use the profiling information collected by running the code compiled by the first compiler.</p>
<h2 id="Reference"><a href="#Reference" class="headerlink" title="Reference"></a>Reference</h2><ul>
<li><a href="https://en.wikipedia.org/wiki/Interpreter_%28computing%29" target="_blank" rel="external">Interpreter (computing)</a></li>
<li><a href="https://en. wikipedia.org/wiki/Just-in-time_compilation" target="_blank" rel="external">Just-in-time compilation</a></li>
<li><a href="https://en.wikipedia.org/wiki/Ahead-of-time_compilation" target="_blank" rel="external">Ahead-of-time compilation</a></li>
<li><a href="http://programmers.stackexchange.com/questions/246094/understanding-the-differences-traditional-interpreter-jit-compiler-jit-interp/269878#269878" target="_blank" rel="external">Understanding the differences: traditional interpreter, JIT compiler, JIT interpreter and AOT compiler</a></li>
</ul>
]]></content>
</entry>
<entry>
<title><![CDATA[理解DOM事件模型]]></title>
<url>http://blog.dzyhenry.com/2016/05/12/dom_event_model/</url>
<content type="html"><![CDATA[<blockquote>
<p>注:本文内容基本都来自W3C文档,所有关键概念都有出处链接,遇到没解释清楚的地方建议直接阅读原文。</p>