-
Notifications
You must be signed in to change notification settings - Fork 22
/
Copy pathnodeblogs.com.feed.xml
4120 lines (3061 loc) · 293 KB
/
nodeblogs.com.feed.xml
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
<rss version="2.0">
<channel>
<title>Nodeblogs.com Feed</title>
<link/>http://www.nodeblogs.com/feed/blogs
<description>Nodeblogs aggregated feed</description>
<pubDate>Fri May 21 2010 08:22:19 GMT+0000 (UTC)</pubDate>
<generator>http://github.com/christkv/node-blogs</generator>
<language>en</language>
<item>
<title>Buffers not the way for mongodb :(</title>
<category>m,o,n,g,o,d,b,,,n,o,d,e,j,s,,,d,e,v,e,l,o,p,m,e,n,t,,,j,a,v,a,s,c,r,i,p,t</category>
<author></author>
<guid>http://christiankvalheim.com/post/612792033</guid>
<link/>http://christiankvalheim.com/post/612792033
<description>&lt;p&gt;I have been working on trying to get the speed up on the mongodb nodejs driver and buffers looked very promising so I decided to attempt to optimize the incoming data streams using buffers the theory being that I would avoid a lot of excessive copying of data back and forth in V8 due to string manipulation.
I had a mini benchmark
&lt;a href="http://github.com/christkv/node-mongodb-native/blob/master/benchmark/streaming_benchmark.js"&gt;benchmark/streaming_benchmark.js&lt;/a&gt;
that was heavy on reading that gave the following results on my macbook pro on the string based version.
&lt;pre&gt;
save recs: 10.02seconds
recs:10000 :: 0.59seconds
recs:20000 :: 1.206seconds
recs:30000 :: 1.829seconds
recs:40000 :: 2.471seconds
recs:50000 :: 3.119seconds
recs:60000 :: 3.745seconds
recs:70000 :: 4.393seconds
recs:80000 :: 5seconds
recs:90000 :: 5.596seconds
recs:100000 :: 6.164seconds
&lt;/pre&gt;
The refactored version using buffers instead of strings and taking advantage that the socket returns a buffer turned out the following numbers.
&lt;pre&gt;
save recs: 8.882seconds
recs:10000 :: 1.719seconds
recs:20000 :: 3.414seconds
recs:30000 :: 5.181seconds
recs:40000 :: 6.949seconds
recs:50000 :: 8.706seconds
recs:60000 :: 10.501seconds
recs:70000 :: 12.235seconds
recs:80000 :: 13.967seconds
recs:90000 :: 15.696seconds
recs:100000 :: 17.423seconds
&lt;/pre&gt;
It’s pretty obvious a no-go at this stage. I suspect that the overhead of interacting with the buffer object is negating any gain in performance from avoiding the garbage collector in v8 but that’s a wild guess from my side at this point.
I did however change the binary storage object to buffers which dropped the memory consumption off the gridstore on large files a fair amount and stopped it from crashing.
However the lesson from that is. Don’t read a 100 MB file into memory and write it out to mongodb in one go. Read it in chunks using fs.read instead of fs.readFile.
I’m gona put the buffer refactoring on hold but if you want to check it out and maybe lend a hand towards understanding why it is so much slower then take a look at the branch
&lt;a href="http://github.com/christkv/node-mongodb-native/tree/buffers_buffers_buffers"&gt;
&lt;a href="http://github.com/christkv/node-mongodb-native/tree/buffers_buffers_buffers"&gt;http://github.com/christkv/node-mongodb-native/tree/buffers_buffers_buffers&lt;/a&gt;
&lt;/a&gt;
Cheers&lt;/p&gt;</description>
<pubDate>Wed May 19 2010 10:00:13 GMT+0000 (UTC)</pubDate>
</item>
<item>
<title>Streaming UTF-8 (with node.js)</title>
<category></category>
<author>[email protected]</author>
<guid>http://www.debuggable.com/posts/streaming-utf-8-with-node-js:4bf28e8b-a290-432f-a222-11c1cbdd56cb</guid>
<link/>http://feedproxy.google.com/~r/debuggable/~3/5B_DXu-vkv0/streaming-utf-8-with-node-js:4bf28e8b-a290-432f-a222-11c1cbdd56cb
<description>&lt;p&gt;&lt;a href="http://en.wikipedia.org/wiki/Utf-8#Description"&gt;UTF-8&lt;/a&gt; is a variable-length character encoding for &lt;a href="http://en.wikipedia.org/wiki/Unicode"&gt;Unicode&lt;/a&gt;. This text is encoded in UTF-8, so the characters you are reading can consist of 1 to 4 bytes. As long as the characters fit within the ASCII range (0-127), there is exactly 1 byte used per character.&lt;/p&gt;
&lt;p&gt;But if I want to express a character outside the ASCII range, such as '¢', I need more bytes. The character '¢' for example consists of: 0xC2 and 0xA2. The first byte, 0xC2, indicates that '¢' is a 2-byte character. This is easy to understand if you look at the binary representation of 0xC2:&lt;/p&gt;
&lt;pre&gt;&lt;code&gt;11000010
&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;As you can see, the bit sequence begins with '110', which as per the UTF-8 specification means: "2 byte character ahead!". Another character such as '€' (0xE2, 0x82, 0xAC) would work the same way. The first byte, 0xE2, looks like this in binary:&lt;/p&gt;
&lt;pre&gt;&lt;code&gt;11100010
&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;The prefix '1110' specifies that there are 3 bytes forming the current character. More exotic characters may even start with '11110', which indicates a 4 byte character.&lt;/p&gt;
&lt;p&gt;As you can guess, UTF-8 text is not trivial to stream. Networks and file systems are not UTF-8 aware, so they will often split a chunk of text in the middle of a character.&lt;/p&gt;
&lt;p&gt;To make sure you don't process a partial character, you have to analyze the last 3 bytes of any given chunk in your stream to check for the bit-prefixes that are used to announce a multibyte character. If you detect an incomplete character, you need to buffer the bytes you have for it, and then prepend them to the next chunk that comes in.&lt;/p&gt;
&lt;p&gt;This way you can completely avoid breaking apart multibyte characters within a UTF-8 text, while still getting great performance and memory usage (only the last 3 bytes need checking / buffering).&lt;/p&gt;
&lt;p&gt;As of yesterday, &lt;a href="http://nodejs.org/"&gt;node.js&lt;/a&gt;'s net / http modules are now fully UTF-8 safe, thanks to the streaming Utf8Decoder (undocumented, API may change) you can see below:&lt;/p&gt;
&lt;p&gt;&lt;div class="clear"&gt;&lt;/div&gt;&lt;div class="code debuggable_sh_js" style="white-space: wrap;white-space: nowrap;"&gt;
&lt;span class="kw2"&gt;var&lt;/span&gt; Buffer = require&lt;span class="br0"&gt;&amp;#40;&lt;/span&gt;&lt;span class="st0"&gt;'buffer'&lt;/span&gt;&lt;span class="br0"&gt;&amp;#41;&lt;/span&gt;.&lt;span class="me1"&gt;Buffer&lt;/span&gt;;&lt;br /&gt;
&lt;br /&gt;
&lt;span class="kw2"&gt;var&lt;/span&gt; Utf8Decoder = exports.&lt;span class="me1"&gt;Utf8Decoder&lt;/span&gt; = &lt;span class="kw2"&gt;function&lt;/span&gt;&lt;span class="br0"&gt;&amp;#40;&lt;/span&gt;&lt;span class="br0"&gt;&amp;#41;&lt;/span&gt; &lt;span class="br0"&gt;&amp;#123;&lt;/span&gt;&lt;br /&gt;
&amp;nbsp; &lt;span class="kw1"&gt;this&lt;/span&gt;.&lt;span class="me1"&gt;charBuffer&lt;/span&gt; = &lt;span class="kw2"&gt;new&lt;/span&gt; Buffer&lt;span class="br0"&gt;&amp;#40;&lt;/span&gt;&lt;span class="nu0"&gt;4&lt;/span&gt;&lt;span class="br0"&gt;&amp;#41;&lt;/span&gt;;&lt;br /&gt;
&amp;nbsp; &lt;span class="kw1"&gt;this&lt;/span&gt;.&lt;span class="me1"&gt;charReceived&lt;/span&gt; = &lt;span class="nu0"&gt;0&lt;/span&gt;;&lt;br /&gt;
&amp;nbsp; &lt;span class="kw1"&gt;this&lt;/span&gt;.&lt;span class="me1"&gt;charLength&lt;/span&gt; = &lt;span class="nu0"&gt;0&lt;/span&gt;;&lt;br /&gt;
&lt;span class="br0"&gt;&amp;#125;&lt;/span&gt;;&lt;br /&gt;
&lt;br /&gt;
Utf8Decoder.&lt;span class="me1"&gt;prototype&lt;/span&gt;.&lt;span class="kw1"&gt;write&lt;/span&gt; = &lt;span class="kw2"&gt;function&lt;/span&gt;&lt;span class="br0"&gt;&amp;#40;&lt;/span&gt;buffer&lt;span class="br0"&gt;&amp;#41;&lt;/span&gt; &lt;span class="br0"&gt;&amp;#123;&lt;/span&gt;&lt;br /&gt;
&amp;nbsp; &lt;span class="kw2"&gt;var&lt;/span&gt; charStr = &lt;span class="st0"&gt;''&lt;/span&gt;;&lt;br /&gt;
&amp;nbsp; &lt;span class="co1"&gt;// if our last write ended with an incomplete multibyte character&lt;/span&gt;&lt;br /&gt;
&amp;nbsp; &lt;span class="kw1"&gt;if&lt;/span&gt; &lt;span class="br0"&gt;&amp;#40;&lt;/span&gt;&lt;span class="kw1"&gt;this&lt;/span&gt;.&lt;span class="me1"&gt;charLength&lt;/span&gt;&lt;span class="br0"&gt;&amp;#41;&lt;/span&gt; &lt;span class="br0"&gt;&amp;#123;&lt;/span&gt;&lt;br /&gt;
&amp;nbsp; &amp;nbsp; &lt;span class="co1"&gt;// determine how many remaining bytes this buffer has to offer for this char&lt;/span&gt;&lt;br /&gt;
&amp;nbsp; &amp;nbsp; &lt;span class="kw2"&gt;var&lt;/span&gt; i = &lt;span class="br0"&gt;&amp;#40;&lt;/span&gt;buffer.&lt;span class="me1"&gt;length&lt;/span&gt; &amp;gt;= &lt;span class="kw1"&gt;this&lt;/span&gt;.&lt;span class="me1"&gt;charLength&lt;/span&gt; - &lt;span class="kw1"&gt;this&lt;/span&gt;.&lt;span class="me1"&gt;charReceived&lt;/span&gt;&lt;span class="br0"&gt;&amp;#41;&lt;/span&gt;&lt;br /&gt;
&amp;nbsp; &amp;nbsp; &amp;nbsp; ? &lt;span class="kw1"&gt;this&lt;/span&gt;.&lt;span class="me1"&gt;charLength&lt;/span&gt; - &lt;span class="kw1"&gt;this&lt;/span&gt;.&lt;span class="me1"&gt;charReceived&lt;/span&gt;&lt;br /&gt;
&amp;nbsp; &amp;nbsp; &amp;nbsp; : buffer.&lt;span class="me1"&gt;length&lt;/span&gt;;&lt;br /&gt;
&lt;br /&gt;
&amp;nbsp; &amp;nbsp; &lt;span class="co1"&gt;// add the new bytes to the char buffer&lt;/span&gt;&lt;br /&gt;
&amp;nbsp; &amp;nbsp; buffer.&lt;span class="me1"&gt;copy&lt;/span&gt;&lt;span class="br0"&gt;&amp;#40;&lt;/span&gt;&lt;span class="kw1"&gt;this&lt;/span&gt;.&lt;span class="me1"&gt;charBuffer&lt;/span&gt;, &lt;span class="kw1"&gt;this&lt;/span&gt;.&lt;span class="me1"&gt;charReceived&lt;/span&gt;, &lt;span class="nu0"&gt;0&lt;/span&gt;, i&lt;span class="br0"&gt;&amp;#41;&lt;/span&gt;;&lt;br /&gt;
&amp;nbsp; &amp;nbsp; &lt;span class="kw1"&gt;this&lt;/span&gt;.&lt;span class="me1"&gt;charReceived&lt;/span&gt; += i;&lt;br /&gt;
&lt;br /&gt;
&amp;nbsp; &amp;nbsp; &lt;span class="kw1"&gt;if&lt;/span&gt; &lt;span class="br0"&gt;&amp;#40;&lt;/span&gt;&lt;span class="kw1"&gt;this&lt;/span&gt;.&lt;span class="me1"&gt;charReceived&lt;/span&gt; &amp;lt; &lt;span class="kw1"&gt;this&lt;/span&gt;.&lt;span class="me1"&gt;charLength&lt;/span&gt;&lt;span class="br0"&gt;&amp;#41;&lt;/span&gt; &lt;span class="br0"&gt;&amp;#123;&lt;/span&gt;&lt;br /&gt;
&amp;nbsp; &amp;nbsp; &amp;nbsp; &lt;span class="co1"&gt;// still not enough chars in this buffer? wait for more ...&lt;/span&gt;&lt;br /&gt;
&amp;nbsp; &amp;nbsp; &amp;nbsp; &lt;span class="kw1"&gt;return&lt;/span&gt;;&lt;br /&gt;
&amp;nbsp; &amp;nbsp; &lt;span class="br0"&gt;&amp;#125;&lt;/span&gt;&lt;br /&gt;
&lt;br /&gt;
&amp;nbsp; &amp;nbsp; &lt;span class="co1"&gt;// get the character that was split&lt;/span&gt;&lt;br /&gt;
&amp;nbsp; &amp;nbsp; charStr = &lt;span class="kw1"&gt;this&lt;/span&gt;.&lt;span class="me1"&gt;charBuffer&lt;/span&gt;.&lt;span class="me1"&gt;slice&lt;/span&gt;&lt;span class="br0"&gt;&amp;#40;&lt;/span&gt;&lt;span class="nu0"&gt;0&lt;/span&gt;, &lt;span class="kw1"&gt;this&lt;/span&gt;.&lt;span class="me1"&gt;charLength&lt;/span&gt;&lt;span class="br0"&gt;&amp;#41;&lt;/span&gt;.&lt;span class="me1"&gt;toString&lt;/span&gt;&lt;span class="br0"&gt;&amp;#40;&lt;/span&gt;&lt;span class="br0"&gt;&amp;#41;&lt;/span&gt;;&lt;br /&gt;
&amp;nbsp; &amp;nbsp; &lt;span class="kw1"&gt;this&lt;/span&gt;.&lt;span class="me1"&gt;charReceived&lt;/span&gt; = &lt;span class="kw1"&gt;this&lt;/span&gt;.&lt;span class="me1"&gt;charLength&lt;/span&gt; = &lt;span class="nu0"&gt;0&lt;/span&gt;;&lt;br /&gt;
&lt;br /&gt;
&amp;nbsp; &amp;nbsp; &lt;span class="kw1"&gt;if&lt;/span&gt; &lt;span class="br0"&gt;&amp;#40;&lt;/span&gt;i == buffer.&lt;span class="me1"&gt;length&lt;/span&gt;&lt;span class="br0"&gt;&amp;#41;&lt;/span&gt; &lt;span class="br0"&gt;&amp;#123;&lt;/span&gt;&lt;br /&gt;
&amp;nbsp; &amp;nbsp; &amp;nbsp; &lt;span class="co1"&gt;// if there are no more bytes in this buffer, just emit our char&lt;/span&gt;&lt;br /&gt;
&amp;nbsp; &amp;nbsp; &amp;nbsp; &lt;span class="kw1"&gt;this&lt;/span&gt;.&lt;span class="me1"&gt;onString&lt;/span&gt;&lt;span class="br0"&gt;&amp;#40;&lt;/span&gt;charStr&lt;span class="br0"&gt;&amp;#41;&lt;/span&gt;&lt;br /&gt;
&amp;nbsp; &amp;nbsp; &amp;nbsp; &lt;span class="kw1"&gt;return&lt;/span&gt;;&lt;br /&gt;
&amp;nbsp; &amp;nbsp; &lt;span class="br0"&gt;&amp;#125;&lt;/span&gt;&lt;br /&gt;
&lt;br /&gt;
&amp;nbsp; &amp;nbsp; &lt;span class="co1"&gt;// otherwise cut of the characters end from the beginning of this buffer&lt;/span&gt;&lt;br /&gt;
&amp;nbsp; &amp;nbsp; buffer = buffer.&lt;span class="me1"&gt;slice&lt;/span&gt;&lt;span class="br0"&gt;&amp;#40;&lt;/span&gt;i, buffer.&lt;span class="me1"&gt;length&lt;/span&gt;&lt;span class="br0"&gt;&amp;#41;&lt;/span&gt;;&lt;br /&gt;
&amp;nbsp; &lt;span class="br0"&gt;&amp;#125;&lt;/span&gt;&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&amp;nbsp; &lt;span class="co1"&gt;// determine how many bytes we have to check at the end of this buffer&lt;/span&gt;&lt;br /&gt;
&amp;nbsp; &lt;span class="kw2"&gt;var&lt;/span&gt; i = &lt;span class="br0"&gt;&amp;#40;&lt;/span&gt;buffer.&lt;span class="me1"&gt;length&lt;/span&gt; &amp;gt;= &lt;span class="nu0"&gt;3&lt;/span&gt;&lt;span class="br0"&gt;&amp;#41;&lt;/span&gt;&lt;br /&gt;
&amp;nbsp; &amp;nbsp; ? &lt;span class="nu0"&gt;3&lt;/span&gt;&lt;br /&gt;
&amp;nbsp; &amp;nbsp; : buffer.&lt;span class="me1"&gt;length&lt;/span&gt;;&lt;br /&gt;
&lt;br /&gt;
&amp;nbsp; &lt;span class="co1"&gt;// figure out if one of the last i bytes of our buffer announces an incomplete char&lt;/span&gt;&lt;br /&gt;
&amp;nbsp; &lt;span class="kw1"&gt;for&lt;/span&gt; &lt;span class="br0"&gt;&amp;#40;&lt;/span&gt;; i &amp;gt; &lt;span class="nu0"&gt;0&lt;/span&gt;; i--&lt;span class="br0"&gt;&amp;#41;&lt;/span&gt; &lt;span class="br0"&gt;&amp;#123;&lt;/span&gt;&lt;br /&gt;
&amp;nbsp; &amp;nbsp; c = buffer&lt;span class="br0"&gt;&amp;#91;&lt;/span&gt;buffer.&lt;span class="me1"&gt;length&lt;/span&gt; - i&lt;span class="br0"&gt;&amp;#93;&lt;/span&gt;;&lt;br /&gt;
&lt;br /&gt;
&amp;nbsp; &amp;nbsp; &lt;span class="co1"&gt;// See http://en.wikipedia.org/wiki/UTF-8#Description&lt;/span&gt;&lt;br /&gt;
&lt;br /&gt;
&amp;nbsp; &amp;nbsp; &lt;span class="co1"&gt;// 110XXXXX&lt;/span&gt;&lt;br /&gt;
&amp;nbsp; &amp;nbsp; &lt;span class="kw1"&gt;if&lt;/span&gt; &lt;span class="br0"&gt;&amp;#40;&lt;/span&gt;i == &lt;span class="nu0"&gt;1&lt;/span&gt; &amp;amp;&amp;amp; c &amp;gt;&amp;gt; &lt;span class="nu0"&gt;5&lt;/span&gt; == 0x06&lt;span class="br0"&gt;&amp;#41;&lt;/span&gt; &lt;span class="br0"&gt;&amp;#123;&lt;/span&gt;&lt;br /&gt;
&amp;nbsp; &amp;nbsp; &amp;nbsp; &lt;span class="kw1"&gt;this&lt;/span&gt;.&lt;span class="me1"&gt;charLength&lt;/span&gt; = &lt;span class="nu0"&gt;2&lt;/span&gt;;&lt;br /&gt;
&amp;nbsp; &amp;nbsp; &amp;nbsp; &lt;span class="kw1"&gt;break&lt;/span&gt;;&lt;br /&gt;
&amp;nbsp; &amp;nbsp; &lt;span class="br0"&gt;&amp;#125;&lt;/span&gt;&lt;br /&gt;
&lt;br /&gt;
&amp;nbsp; &amp;nbsp; &lt;span class="co1"&gt;// 1110XXXX&lt;/span&gt;&lt;br /&gt;
&amp;nbsp; &amp;nbsp; &lt;span class="kw1"&gt;if&lt;/span&gt; &lt;span class="br0"&gt;&amp;#40;&lt;/span&gt;i &amp;lt;= &lt;span class="nu0"&gt;2&lt;/span&gt; &amp;amp;&amp;amp; c &amp;gt;&amp;gt; &lt;span class="nu0"&gt;4&lt;/span&gt; == 0x0E&lt;span class="br0"&gt;&amp;#41;&lt;/span&gt; &lt;span class="br0"&gt;&amp;#123;&lt;/span&gt;&lt;br /&gt;
&amp;nbsp; &amp;nbsp; &amp;nbsp; &lt;span class="kw1"&gt;this&lt;/span&gt;.&lt;span class="me1"&gt;charLength&lt;/span&gt; = &lt;span class="nu0"&gt;3&lt;/span&gt;;&lt;br /&gt;
&amp;nbsp; &amp;nbsp; &amp;nbsp; &lt;span class="kw1"&gt;break&lt;/span&gt;;&lt;br /&gt;
&amp;nbsp; &amp;nbsp; &lt;span class="br0"&gt;&amp;#125;&lt;/span&gt;&lt;br /&gt;
&lt;br /&gt;
&amp;nbsp; &amp;nbsp; &lt;span class="co1"&gt;// 11110XXX&lt;/span&gt;&lt;br /&gt;
&amp;nbsp; &amp;nbsp; &lt;span class="kw1"&gt;if&lt;/span&gt; &lt;span class="br0"&gt;&amp;#40;&lt;/span&gt;i &amp;lt;= &lt;span class="nu0"&gt;3&lt;/span&gt; &amp;amp;&amp;amp; c &amp;gt;&amp;gt; &lt;span class="nu0"&gt;3&lt;/span&gt; == 0x1E&lt;span class="br0"&gt;&amp;#41;&lt;/span&gt; &lt;span class="br0"&gt;&amp;#123;&lt;/span&gt;&lt;br /&gt;
&amp;nbsp; &amp;nbsp; &amp;nbsp; &lt;span class="kw1"&gt;this&lt;/span&gt;.&lt;span class="me1"&gt;charLength&lt;/span&gt; = &lt;span class="nu0"&gt;4&lt;/span&gt;;&lt;br /&gt;
&amp;nbsp; &amp;nbsp; &amp;nbsp; &lt;span class="kw1"&gt;break&lt;/span&gt;;&lt;br /&gt;
&amp;nbsp; &amp;nbsp; &lt;span class="br0"&gt;&amp;#125;&lt;/span&gt;&lt;br /&gt;
&amp;nbsp; &lt;span class="br0"&gt;&amp;#125;&lt;/span&gt;&lt;br /&gt;
&lt;br /&gt;
&amp;nbsp; &lt;span class="kw1"&gt;if&lt;/span&gt; &lt;span class="br0"&gt;&amp;#40;&lt;/span&gt;!&lt;span class="kw1"&gt;this&lt;/span&gt;.&lt;span class="me1"&gt;charLength&lt;/span&gt;&lt;span class="br0"&gt;&amp;#41;&lt;/span&gt; &lt;span class="br0"&gt;&amp;#123;&lt;/span&gt;&lt;br /&gt;
&amp;nbsp; &amp;nbsp; &lt;span class="co1"&gt;// no incomplete char at the end of this buffer, emit the whole thing&lt;/span&gt;&lt;br /&gt;
&amp;nbsp; &amp;nbsp; &lt;span class="kw1"&gt;this&lt;/span&gt;.&lt;span class="me1"&gt;onString&lt;/span&gt;&lt;span class="br0"&gt;&amp;#40;&lt;/span&gt;charStr+buffer.&lt;span class="me1"&gt;toString&lt;/span&gt;&lt;span class="br0"&gt;&amp;#40;&lt;/span&gt;&lt;span class="br0"&gt;&amp;#41;&lt;/span&gt;&lt;span class="br0"&gt;&amp;#41;&lt;/span&gt;;&lt;br /&gt;
&amp;nbsp; &amp;nbsp; &lt;span class="kw1"&gt;return&lt;/span&gt;;&lt;br /&gt;
&amp;nbsp; &lt;span class="br0"&gt;&amp;#125;&lt;/span&gt;&lt;br /&gt;
&lt;br /&gt;
&amp;nbsp; &lt;span class="co1"&gt;// buffer the incomplete character bytes we got&lt;/span&gt;&lt;br /&gt;
&amp;nbsp; buffer.&lt;span class="me1"&gt;copy&lt;/span&gt;&lt;span class="br0"&gt;&amp;#40;&lt;/span&gt;&lt;span class="kw1"&gt;this&lt;/span&gt;.&lt;span class="me1"&gt;charBuffer&lt;/span&gt;, &lt;span class="nu0"&gt;0&lt;/span&gt;, buffer.&lt;span class="me1"&gt;length&lt;/span&gt; - i, buffer.&lt;span class="me1"&gt;length&lt;/span&gt;&lt;span class="br0"&gt;&amp;#41;&lt;/span&gt;;&lt;br /&gt;
&amp;nbsp; &lt;span class="kw1"&gt;this&lt;/span&gt;.&lt;span class="me1"&gt;charReceived&lt;/span&gt; = i;&lt;br /&gt;
&lt;br /&gt;
&amp;nbsp; &lt;span class="kw1"&gt;if&lt;/span&gt; &lt;span class="br0"&gt;&amp;#40;&lt;/span&gt;buffer.&lt;span class="me1"&gt;length&lt;/span&gt; - i &amp;gt; &lt;span class="nu0"&gt;0&lt;/span&gt;&lt;span class="br0"&gt;&amp;#41;&lt;/span&gt; &lt;span class="br0"&gt;&amp;#123;&lt;/span&gt;&lt;br /&gt;
&amp;nbsp; &amp;nbsp; &lt;span class="co1"&gt;// buffer had more bytes before the incomplete char, emit them&lt;/span&gt;&lt;br /&gt;
&amp;nbsp; &amp;nbsp; &lt;span class="kw1"&gt;this&lt;/span&gt;.&lt;span class="me1"&gt;onString&lt;/span&gt;&lt;span class="br0"&gt;&amp;#40;&lt;/span&gt;charStr+buffer.&lt;span class="me1"&gt;slice&lt;/span&gt;&lt;span class="br0"&gt;&amp;#40;&lt;/span&gt;&lt;span class="nu0"&gt;0&lt;/span&gt;, buffer.&lt;span class="me1"&gt;length&lt;/span&gt; - i&lt;span class="br0"&gt;&amp;#41;&lt;/span&gt;.&lt;span class="me1"&gt;toString&lt;/span&gt;&lt;span class="br0"&gt;&amp;#40;&lt;/span&gt;&lt;span class="br0"&gt;&amp;#41;&lt;/span&gt;&lt;span class="br0"&gt;&amp;#41;&lt;/span&gt;;&lt;br /&gt;
&amp;nbsp; &lt;span class="br0"&gt;&amp;#125;&lt;/span&gt; &lt;span class="kw1"&gt;else&lt;/span&gt; &lt;span class="kw1"&gt;if&lt;/span&gt; &lt;span class="br0"&gt;&amp;#40;&lt;/span&gt;charStr&lt;span class="br0"&gt;&amp;#41;&lt;/span&gt; &lt;span class="br0"&gt;&amp;#123;&lt;/span&gt;&lt;br /&gt;
&amp;nbsp; &amp;nbsp; &lt;span class="co1"&gt;// or just emit the charStr if any&lt;/span&gt;&lt;br /&gt;
&amp;nbsp; &amp;nbsp; &lt;span class="kw1"&gt;this&lt;/span&gt;.&lt;span class="me1"&gt;onString&lt;/span&gt;&lt;span class="br0"&gt;&amp;#40;&lt;/span&gt;charStr&lt;span class="br0"&gt;&amp;#41;&lt;/span&gt;;&lt;br /&gt;
&amp;nbsp; &lt;span class="br0"&gt;&amp;#125;&lt;/span&gt;&lt;br /&gt;
&lt;span class="br0"&gt;&amp;#125;&lt;/span&gt;;&lt;/div&gt;&lt;/p&gt;
&lt;p&gt;I feel like this implementation could still be somewhat simplified, so if you have any suggestions or comments, please let me know!&lt;/p&gt;
&lt;p&gt;--fg&lt;/p&gt;
&lt;p&gt;PS: Another buffer-based project I'm working on is a fast multipart parser - stay tuned for another post!&lt;/p&gt;
&lt;p&gt;&lt;img style="display: none;" src="http://www.debuggable.com/posts/tick/4bf28e8b-a290-432f-a222-11c1cbdd56cb"&gt;&lt;/p&gt;&lt;img src="http://feeds.feedburner.com/~r/debuggable/~4/5B_DXu-vkv0" height="1" width="1"/&gt;</description>
<pubDate>Tue May 18 2010 13:03:23 GMT+0000 (UTC)</pubDate>
</item>
<item>
<title>A simple insert and query using node.js mongodb driver</title>
<category>m,o,n,g,o,d,b,,,n,o,d,e,j,s,,,s,i,m,p,l,e,,,t,u,t,o,r,i,a,l,,,j,a,v,a,s,c,r,i,p,t</category>
<author></author>
<guid>http://christiankvalheim.com/post/596160094</guid>
<link/>http://christiankvalheim.com/post/596160094
<description>Let’s start with a simple nodejs mongo example opening the db, inserting a document, querying for the document by a field, changing the document and saving the updated document back to mongo before closing the database.
&lt;pre&gt;&lt;code class="javascript"&gt;
// Let's get the 'Classes' used for the driver
var Db = require('mongodb').Db,
Server = require('mongodb').Server;
// Open a connection to your mongodb server for the database 'simple_tutorial'
// pass in the option for auto_reconnect (in case the server dies the connection
// will restart
new Db('simple_tutorial',
new Server("127.0.0.1", 27017, {auto_reconnect: false}), {}).open(function(err, db) {
// Let's grab a collection/table
db.collection('documents', function(err, collection) {
// Now's time to insert our brilliant document for permanent storage
collection.insert({awesome:1, info:{type:'binary'}}, function(err, doc) {
// The document is inserted asynchronous so control is instantly returned to
// the calling code thus allowing high write speed, the unique id is actually
// assigned by the client driver not the mongodb server. you can override
// the default key factory (see integration_tests.js that comes with the)
// the driver
// Let's fetch the document using the collection.findOne method
collection.findOne({awesome:1}, function(err, document) {
// Let's change the info field to something else and update the object
// in the collection (you can use the collection.save method if you want
// to update using the document id as the identifier otherwise you have
// to pass in the query that selects the document you wish to update
document.info = {type:'silly'};
collection.update({awesome:1}, document, function(err, document) {
// Document updated in the database, let's finish off by closing
// the db connection and thus ending the execution
db.close();
});
});
});
});
}
&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;
That’s a very simple little introduction to the use of the ‘VERY’ basic functionality of the node-mongodb-native driver you can find at
&lt;/p&gt;
&lt;p&gt;
&lt;a href="http://github.com/christkv/node-mongodb-native"&gt;&lt;a href="http://github.com/christkv/node-mongodb-native"&gt;http://github.com/christkv/node-mongodb-native&lt;/a&gt;&lt;/a&gt;
&lt;/p&gt;
&lt;p&gt;
I hope to do more in-depth topics going forward or answers to questions I’m asked by people using the driver to write they applications.
&lt;/p&gt;</description>
<pubDate>Thu May 13 2010 21:38:41 GMT+0000 (UTC)</pubDate>
</item>
<item>
<title>Getting started</title>
<category></category>
<author></author>
<guid>http://christiankvalheim.com/post/595875746</guid>
<link/>http://christiankvalheim.com/post/595875746
<description>&lt;p&gt;Hi&lt;/p&gt;
&lt;p&gt;I finally got my ass out of my chair and signed up for a blog. Over the next couple of weeks I’ll be posting a lot of information and hopefully tips and tricks on how to use the nodejs open source projects I have published or are interested in.&lt;/p&gt;
&lt;p&gt;Once in a while other musings on software development and working with developers will probably be posted but that will be more of the exception.&lt;/p&gt;
&lt;p&gt;I also have a small project that I’m currently working on that I’m thinking of as a long term business idea. I’m gona try something new. Instead of aiming for the 1 Million dollar startup idea I’m going to aim for a service that will do what I need for it to do and that can be a payed subscription service in the future. Focus will also be on creating a real community around the product and maybe even look at some new ways of organizing the use of income from the project. Hopefully it can be a mom-and-pop business that I will focus on for the rest of my working life.&lt;/p&gt;
&lt;p&gt;I believe our business would be much better served if we had more 2-3 people shops supporting products long term as a passionate private business instead of aiming for the lottery payout of a venture-backed startup. It also puts a perspective on the work that means you are not rushing like crazy to build features and focus on the long term viability of the business and product.&lt;/p&gt;
&lt;p&gt;Cheers&lt;/p&gt;</description>
<pubDate>Thu May 13 2010 19:20:42 GMT+0000 (UTC)</pubDate>
</item>
<item>
<title>Understanding node.js</title>
<category></category>
<author>[email protected]</author>
<guid>http://www.debuggable.com/posts/understanding-node-js:4bd98440-45e4-4a9a-8ef7-0f7ecbdd56cb</guid>
<link/>http://feedproxy.google.com/~r/debuggable/~3/qf8IvkdIyLA/understanding-node-js:4bd98440-45e4-4a9a-8ef7-0f7ecbdd56cb
<description>&lt;p&gt;&lt;a href="http://nodejs.org/"&gt;Node.js&lt;/a&gt; has generally caused two reactions in people I've introduced it to. Basically people either "got it" right away, or they ended up being very confused.&lt;/p&gt;
&lt;p&gt;If you have been in the second group so far, here is my attempt to explain node:&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;It is a command line tool. You download a tarball, compile and install the source.&lt;/li&gt;
&lt;li&gt;It let's you run JavaScript programs by typing 'node my_app.js' in your terminal.&lt;/li&gt;
&lt;li&gt;The JS is executed by the &lt;a href="http://code.google.com/p/v8/"&gt;V8 javascript engine&lt;/a&gt; (the thing that makes Google Chrome so fast).&lt;/li&gt;
&lt;li&gt;Node provides a JavaScript API to access the network and file system&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;&lt;strong&gt;&lt;em&gt;"But I can do everything I need in: ruby, python, php, java, ... !".&lt;/em&gt;&lt;/strong&gt;&lt;/p&gt;
&lt;p&gt;I hear you. And you are right! Node is no freaking unicorn that will come and do your work for you, sorry. It's just a tool, and it probably won't replace your regular tools completely, at least not for now.&lt;/p&gt;
&lt;p&gt;&lt;strong&gt;&lt;em&gt;"Get to the point!"&lt;/em&gt;&lt;/strong&gt;&lt;/p&gt;
&lt;p&gt;Alright, I will. Node is basically very good when you need to do several things at the same time. Have you ever written a piece of code and said "I wish this would run in parallel"? Well, in node everything runs in parallel, except your code.&lt;/p&gt;
&lt;p&gt;&lt;strong&gt;&lt;em&gt;"Huh?"&lt;/em&gt;&lt;/strong&gt;&lt;/p&gt;
&lt;p&gt;That's right, &lt;em&gt;everything runs in parallel, except your code&lt;/em&gt;. To understand that, imagine your code is the king, and node is his army of servants.&lt;/p&gt;
&lt;p&gt;The day starts by one servant waking up the king and asking him if he needs anything. The king gives the servant a list of tasks and goes back to sleep a little longer. The servant now distributes those tasks among his colleagues and they get to work.&lt;/p&gt;
&lt;p&gt;Once a servant finishes a task, he lines up outside the kings quarter to report. The king lets one servant in at a time, and listens to things he reports. Sometimes the king will give the servant more tasks on the way out.&lt;/p&gt;
&lt;p&gt;Life is good, for the king's servants carry out all of his tasks in parallel, but only report with one result at a time, so the king can focus. *&lt;/p&gt;
&lt;p&gt;&lt;strong&gt;&lt;em&gt;"That's fantastic, but could you quit the silly metaphor and speak geek to me?"&lt;/em&gt;&lt;/strong&gt;&lt;/p&gt;
&lt;p&gt;Sure. A simple node program may look like this:&lt;/p&gt;
&lt;p&gt;&lt;div class="clear"&gt;&lt;/div&gt;&lt;div class="code debuggable_sh_js" style="white-space: wrap;white-space: nowrap;"&gt;
&lt;span class="kw2"&gt;var&lt;/span&gt; fs = require&lt;span class="br0"&gt;&amp;#40;&lt;/span&gt;&lt;span class="st0"&gt;'fs'&lt;/span&gt;&lt;span class="br0"&gt;&amp;#41;&lt;/span&gt;&lt;br /&gt;
&amp;nbsp; , sys = require&lt;span class="br0"&gt;&amp;#40;&lt;/span&gt;&lt;span class="st0"&gt;'sys'&lt;/span&gt;&lt;span class="br0"&gt;&amp;#41;&lt;/span&gt;;&lt;br /&gt;
&lt;br /&gt;
fs.&lt;span class="me1"&gt;readFile&lt;/span&gt;&lt;span class="br0"&gt;&amp;#40;&lt;/span&gt;&lt;span class="st0"&gt;'treasure-chamber-report.txt'&lt;/span&gt;, &lt;span class="kw2"&gt;function&lt;/span&gt;&lt;span class="br0"&gt;&amp;#40;&lt;/span&gt;report&lt;span class="br0"&gt;&amp;#41;&lt;/span&gt; &lt;span class="br0"&gt;&amp;#123;&lt;/span&gt;&lt;br /&gt;
&amp;nbsp; sys.&lt;span class="me1"&gt;puts&lt;/span&gt;&lt;span class="br0"&gt;&amp;#40;&lt;/span&gt;&lt;span class="st0"&gt;&amp;quot;oh, look at all my money: &amp;quot;&lt;/span&gt;+report&lt;span class="br0"&gt;&amp;#41;&lt;/span&gt;;&lt;br /&gt;
&lt;span class="br0"&gt;&amp;#125;&lt;/span&gt;&lt;span class="br0"&gt;&amp;#41;&lt;/span&gt;;&lt;br /&gt;
&lt;br /&gt;
fs.&lt;span class="me1"&gt;writeFile&lt;/span&gt;&lt;span class="br0"&gt;&amp;#40;&lt;/span&gt;&lt;span class="st0"&gt;'letter-to-princess.txt'&lt;/span&gt;, &lt;span class="st0"&gt;'...'&lt;/span&gt;, &lt;span class="kw2"&gt;function&lt;/span&gt;&lt;span class="br0"&gt;&amp;#40;&lt;/span&gt;&lt;span class="br0"&gt;&amp;#41;&lt;/span&gt; &lt;span class="br0"&gt;&amp;#123;&lt;/span&gt;&lt;br /&gt;
&amp;nbsp; sys.&lt;span class="me1"&gt;puts&lt;/span&gt;&lt;span class="br0"&gt;&amp;#40;&lt;/span&gt;&lt;span class="st0"&gt;&amp;quot;can't wait to hear back from her!&amp;quot;&lt;/span&gt;&lt;span class="br0"&gt;&amp;#41;&lt;/span&gt;;&lt;br /&gt;
&lt;span class="br0"&gt;&amp;#125;&lt;/span&gt;&lt;span class="br0"&gt;&amp;#41;&lt;/span&gt;;&lt;/div&gt;&lt;/p&gt;
&lt;p&gt;Your code gives node the two tasks to read and write a file, and then goes to sleep. Once node has completed a task, the callback for it is fired. But there can only be one callback firing at the same time. Until that callback has finished executing, all other callbacks have to wait in line. In addition to that, there is no guarantee on the order in which the callbacks will fire.&lt;/p&gt;
&lt;p&gt;&lt;strong&gt;&lt;em&gt;"So I don't have to worry about code accessing the same data structures at the same time?"&lt;/em&gt;&lt;/strong&gt;&lt;/p&gt;
&lt;p&gt;You got it! That's the entire beauty of JavaScripts single-threaded / event loop design!&lt;/p&gt;
&lt;p&gt;&lt;strong&gt;&lt;em&gt;"Very nice, but why should I use it?"&lt;/em&gt;&lt;/strong&gt;&lt;/p&gt;
&lt;p&gt;One reason is efficiency. In a web application, your main response time cost is usually the sum of time it takes to execute all your database queries. With node, you can execute all your queries at once, reducing the response time to the duration it takes to execute the slowest query.&lt;/p&gt;
&lt;p&gt;Another reason is JavaScript. You can use node to share code between the browser and your backend. JavaScript is also on its way to become a really universal language. No matter if you did python, ruby, java, php, ... in the past, you've probably picked up some JS along the way, right?&lt;/p&gt;
&lt;p&gt;And the last reason is raw speed. V8 is constantly pushing the boundaries in being one of the fastest dynamic language interpreters on the planet. I can't think of any other language that is being pushed for speed as aggressively as JavaScript is right now. In addition to that, node's I/O facilities are really light weight, bringing you as close to fully utilizing your system's full I/O capacities as possible.&lt;/p&gt;
&lt;p&gt;&lt;strong&gt;&lt;em&gt;"So you are saying I should write all my apps in node from now on?"&lt;/em&gt;&lt;/strong&gt;&lt;/p&gt;
&lt;p&gt;Yes and no. Once you start to swing the node hammer, everything is obviously going to start looking like a nail. But if you're working on something with a deadline, you might want to base your decision on:&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;Are low response times / high concurrency important? Node is really good at that.&lt;/li&gt;
&lt;li&gt;How big is the project? Small projects should be fine. Big projects should evaluate carefully (available libraries, resources to fix a bug or two upstream, etc.).&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;&lt;strong&gt;&lt;em&gt;"Does node run on Windows?"&lt;/em&gt;&lt;/strong&gt;&lt;/p&gt;
&lt;p&gt;No. If you are on windows, you need to run a virtual machine (I recommend &lt;a href="http://www.virtualbox.org/"&gt;VirtualBox&lt;/a&gt;) with Linux. Windows support for node is planned, but don't hold your breath for the next few months unless you want to help with the port.&lt;/p&gt;
&lt;p&gt;&lt;strong&gt;&lt;em&gt;"Can I access the DOM in node?"&lt;/em&gt;&lt;/strong&gt;&lt;/p&gt;
&lt;p&gt;Excellent question! No, the DOM is a browser thingy, and node's JS engine (V8) is thankfully totally separate from all that mess. However, there are people working on implementing &lt;a href="http://www.yuiblog.com/blog/2010/04/09/node-js-yui-3-dom-manipulation-oh-my/"&gt;the DOM as a node module&lt;/a&gt;, which may open very exciting possibilities such as unit testing client-side code.&lt;/p&gt;
&lt;p&gt;&lt;strong&gt;&lt;em&gt;"Isn't event driven programming really hard?"&lt;/em&gt;&lt;/strong&gt;&lt;/p&gt;
&lt;p&gt;That depends on you. If you already learned how to juggle AJAX calls and user events in the browser, getting used to node shouldn't be a problem.&lt;/p&gt;
&lt;p&gt;Either way, test driven development can really help you to come up with maintainable designs.&lt;/p&gt;
&lt;p&gt;&lt;strong&gt;&lt;em&gt;"Who is using it?"&lt;/em&gt;&lt;/strong&gt;&lt;/p&gt;
&lt;p&gt;There is a small / incomplete list in the &lt;a href="http://wiki.github.com/ry/node"&gt;node wiki&lt;/a&gt; (scroll to "Companies using Node"). &lt;a href="http://www.yuiblog.com/blog/2010/04/09/node-js-yui-3-dom-manipulation-oh-my/"&gt;Yahoo&lt;/a&gt; is experimenting with node for YUI, &lt;a href="http://www.plurk.com/"&gt;Plurk&lt;/a&gt; is using it for massive comet and Paul Bakaus (of jQuery UI fame) is building a &lt;a href="http://ajaxian.com/archives/aves-game-engine"&gt;mind-blowing game engine&lt;/a&gt; that has some node in the backend. &lt;a href="http://www.joyent.com/"&gt;Joyent&lt;/a&gt; has hired Ryan Dahl (the creator of node) and heavily sponsors the development.&lt;/p&gt;
&lt;p&gt;Oh, and Heroku just announced (experimental ) &lt;a href="http://blog.heroku.com/archives/2010/4/28/node_js_support_experimental/"&gt;hosting support for node.js&lt;/a&gt; as well.&lt;/p&gt;
&lt;p&gt;&lt;strong&gt;&lt;em&gt;"Where can I learn more?"&lt;/em&gt;&lt;/strong&gt;&lt;/p&gt;
&lt;p&gt;Tim Caswell is running the excellent &lt;a href="http://howtonode.org/"&gt;How To Node&lt;/a&gt; blog. Follow &lt;a href="http://search.twitter.com/search?q=%23nodejs"&gt;#nodejs&lt;/a&gt; on twitter. Subscribe to the &lt;a href="http://groups.google.com/group/nodejs"&gt;mailing list&lt;/a&gt;. And come and hang out in the IRC channel, &lt;em&gt;#node.js&lt;/em&gt; (yes, the dot is in the name). We're close to hitting the 200 lurker-mark there soon : ).&lt;/p&gt;
&lt;p&gt;I'll also continue to write articles here on &lt;a href="http://debuggable.com/"&gt;debuggable.com&lt;/a&gt;.&lt;/p&gt;
&lt;p&gt;That's it for now. Feel free to comment if you have more questions!&lt;/p&gt;
&lt;p&gt;--fg&lt;/p&gt;
&lt;p&gt;*: The metaphor is obviously a simplification, but if it's hard to find a counterpart for the concept of non-blocking in reality.&lt;/p&gt;
&lt;p&gt;&lt;img style="display: none;" src="http://www.debuggable.com/posts/tick/4bd98440-45e4-4a9a-8ef7-0f7ecbdd56cb"&gt;&lt;/p&gt;&lt;img src="http://feeds.feedburner.com/~r/debuggable/~4/qf8IvkdIyLA" height="1" width="1"/&gt;</description>
<pubDate>Thu Apr 29 2010 13:06:08 GMT+0000 (UTC)</pubDate>
</item>
<item>
<title>Quitting open source</title>
<category></category>
<author>[email protected]</author>
<guid>http://www.debuggable.com/posts/quitting-open-source:4bb448b6-6414-45a3-a282-16c7cbdd56cb</guid>
<link/>http://feedproxy.google.com/~r/debuggable/~3/BVubEW8t1RM/quitting-open-source:4bb448b6-6414-45a3-a282-16c7cbdd56cb
<description>&lt;p&gt;&lt;strong&gt;Update:&lt;/strong&gt; Yes, this of course was an April fools joke : )&lt;/p&gt;
&lt;p&gt;This is a decision that has not been easy for us. Over the years, Tim and I build our reputation and company on the basis of open source. For a long time we worked on &lt;a href="http://cakephp.org/"&gt;CakePHP&lt;/a&gt;, and more recently I became very involved with &lt;a href="http://nodejs.org/"&gt;node.js&lt;/a&gt;.&lt;/p&gt;
&lt;p&gt;Generally, open source has been very good to us. We learned a lot about programming, collaborated with great people and, thanks to our clients, made payroll consistently.&lt;/p&gt;
&lt;p&gt;But sometimes, even if things are good, you have to evaluate if they are aligned with your true goals. And today, we finally decided they are not. Our goals and the nature of open source are in fundamental conflict.&lt;/p&gt;
&lt;p&gt;What changed? Well, when we initially started debuggable, our goal was to build commercial web applications and make a living from that. But it turns out, that is actually really hard.&lt;/p&gt;
&lt;p&gt;37signals may wash your head about getting real until it comes off, but the truth is:&lt;/p&gt;
&lt;p&gt;You will not build a product like basecamp with a limit of 10h / week. And you certainly will not, let me stress that, develop an open source technology like Ruby on Rails along the way, which will then help you promote your product(s). 37signals either got insanely lucky, or they are glorifying their story after the fact. It is probably both.&lt;/p&gt;
&lt;p&gt;This leads back to our decision. We have concluded, that in order to reach our goals for 2010, we need more time. It is not really possible to cut on client work, since we've got bills to pay. So instead, we will drastically cut on our open source involvement.&lt;/p&gt;
&lt;p&gt;Beginning today, we will only work on open source, if we actually really need a critical bug fixed, and the maintainer of the project refuses to fix it for us. We will only send those bug fixes upstream, if the patches are big enough so it would be more difficult for us to maintain them privately.&lt;/p&gt;
&lt;p&gt;We estimate that this will free us 20 hours / week. Those hours, for now, will be used to finally get &lt;a href="http://transloadit.com/"&gt;transloadit.com&lt;/a&gt; out of the testing phase. At the same time, we are evaluating a more radical technology change. We recently developed our first native iPhone application for a client, and it is a truly great plattform. Also the iPad seems like a great opportunity we shouldn't miss. So I wouldn't be surprised if Tim and I would be moving to the App Store ecosystem at some point.&lt;/p&gt;
&lt;p&gt;So fare well, open source community. We are sorry we can longer be a part. Our website will be updated to reflect our new philosophy by tomorrow.&lt;/p&gt;
&lt;p&gt;-- Felix &amp;amp; Tim&lt;/p&gt;
&lt;p&gt;&lt;img style="display: none;" src="http://www.debuggable.com/posts/tick/4bb448b6-6414-45a3-a282-16c7cbdd56cb"&gt;&lt;/p&gt;&lt;img src="http://feeds.feedburner.com/~r/debuggable/~4/BVubEW8t1RM" height="1" width="1"/&gt;</description>
<pubDate>Thu Apr 01 2010 07:38:17 GMT+0000 (UTC)</pubDate>
</item>
<item>
<title>Hello Node!</title>
<category></category>
<author>[email protected] (Tim Caswell)</author>
<guid>http://howtonode.org/hello-node</guid>
<link/>http://howtonode.org/hello-node
<description>&lt;p&gt;In programming literature it has become the standard to create a hello world program as the first example. This article will go through a few simple hello world type examples with everything from simple terminal output to an http server that uses an external framework for some semantic sugar.&lt;/p&gt;
&lt;p&gt;Then we'll shift gears and go through a real example that teaches enough to get you up on your feet writing your own web application using node.JS.&lt;/p&gt;
&lt;h2&gt;Hello World Examples&lt;/h2&gt;
&lt;p&gt;Here are four simple hello world examples. The comments in the code explain how the code works and the text around it explain what it does and how to test it.&lt;/p&gt;
&lt;h2&gt;Hello Console&lt;/h2&gt;
&lt;p&gt;This example is about as plain as it can get. It prints the words "Hello World" to the terminal.&lt;/p&gt;
&lt;div class="snippet"&gt;&lt;a href="hello-node/hello-console.js" class="code-link"&gt;hello-console.js&lt;/a&gt;&lt;pre&gt;&lt;code&gt;// Load the sys module since we want to write to the terminal
var sys = require('sys');
// Call the puts function on the sys module.
sys.puts(&amp;quot;Hello World&amp;quot;);&lt;/code&gt;&lt;/pre&gt;&lt;dl class="output"&gt;&lt;dt&gt;Output&lt;/dt&gt;&lt;dd&gt;Hello World
&lt;/dd&gt;&lt;/dl&gt;&lt;/div&gt;
&lt;p&gt;You can run this by putting it in a file called "hello-console.js" and running it with &lt;code&gt;node hello-console.js&lt;/code&gt;&lt;/p&gt;
&lt;h2&gt;Hello HTTP&lt;/h2&gt;
&lt;p&gt;I'd guess that while it's not the only use case for node.JS, most people are using it as a web application platform. So the next example will be a simple HTTP server that responds to every request with the plain text message "Hello World"&lt;/p&gt;
&lt;div class="snippet"&gt;&lt;a href="hello-node/hello-http.js" class="code-link"&gt;hello-http.js&lt;/a&gt;&lt;pre&gt;&lt;code&gt;// Load the sys module for console writing.
var sys = require('sys');
// Load the http module to create an http server.
var http = require('http');
// Configure our HTTP server to respond with Hello World to all requests.
var server = http.createServer(function (request, response) {
response.writeHead(200, {&amp;quot;Content-Type&amp;quot;: &amp;quot;text/plain&amp;quot;});
response.write(&amp;quot;Hello World\n&amp;quot;);
response.close();
});
// Listen on port 8000, IP defaults to 127.0.0.1
server.listen(8000);
// Put a friendly message on the terminal
sys.puts(&amp;quot;Server running at http://127.0.0.1:8000/&amp;quot;);
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;
&lt;h2&gt;Hello TCP&lt;/h2&gt;
&lt;p&gt;Node also makes an excellent TCP server, and here is an example that responds to all TCP connections with the message "Hello World" and then closes the connection.&lt;/p&gt;
&lt;div class="snippet"&gt;&lt;a href="hello-node/hello-tcp.js" class="code-link"&gt;hello-tcp.js&lt;/a&gt;&lt;pre&gt;&lt;code&gt;// Load the sys module for console writing.
var sys = require('sys');
// Load the net module to create a tcp server.
var net = require('net');
// Setup a tcp server
var server = net.createServer(function (socket) {
// Every time someone connects, tell them hello and then close the connection.
socket.addListener(&amp;quot;connect&amp;quot;, function () {
sys.puts(&amp;quot;Connection from &amp;quot; + socket.remoteAddress);
socket.write(&amp;quot;Hello World\n&amp;quot;);
socket.end();
});
});
// Fire up the server bound to port 7000 on localhost
server.listen(7000, &amp;quot;localhost&amp;quot;);
// Put a friendly message on the terminal
sys.puts(&amp;quot;TCP server listening on port 7000 at localhost.&amp;quot;);
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;
&lt;h2&gt;Hello Router&lt;/h2&gt;
&lt;p&gt;Often you won't be using the node built-in libraries because they are designed to be very low level. This makes node quick, nimble, and easy to maintain, but is usually not enough to get started on a real world application. My first node framework is &lt;code&gt;node-router&lt;/code&gt;. This example shows an HTTP server that responds with "Hello World" to all requests to "/" and responds with a 404 error to everything else.&lt;/p&gt;
&lt;div class="snippet"&gt;&lt;a href="hello-node/hello-router.js" class="code-link"&gt;hello-router.js&lt;/a&gt;&lt;pre&gt;&lt;code&gt;// Load the node-router library by creationix
var server = require('node-router').getServer();
// Configure our HTTP server to respond with Hello World the root request
server.get(&amp;quot;/&amp;quot;, function (request, response) {
response.simpleText(200, &amp;quot;Hello World!&amp;quot;);
});
// Listen on port 8080 on localhost
server.listen(8000, &amp;quot;localhost&amp;quot;);&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;
&lt;p&gt;In order to test this, you will need to install the &lt;code&gt;node-router&lt;/code&gt; library. There are two ways to do this. You can either install it into a path that node recognizes (I create a symlink into ~/.node_libraries) or put the &lt;code&gt;node-router.js&lt;/code&gt; file in your application and reference it locally. See the &lt;a href="http://nodejs.org/api.html#_modules"&gt;node docs on modules&lt;/a&gt; for more details on how modules work.&lt;/p&gt;
&lt;h1&gt;Installing Libraries&lt;/h1&gt;
&lt;p&gt;I'll install the following libraries that are common to my projects:&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;&lt;a href="http://github.com/creationix/node-router"&gt;node-router&lt;/a&gt; - Wraps the built-in http library with many convenience functions like request routing and message body decoding.&lt;/li&gt;
&lt;li&gt;&lt;a href="http://github.com/creationix/haml-js"&gt;haml-js&lt;/a&gt; - Template engine that compiles HAML templates into HTML&lt;/li&gt;
&lt;li&gt;&lt;a href="http://github.com/creationix/proto"&gt;proto&lt;/a&gt; - Baby library that adds some useful stuff to Object.prototype&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;You can install these however you please, but here is how I'd do it. The following code will clone the four libraries and install them into your local node library search path:&lt;/p&gt;
&lt;div class="snippet"&gt;&lt;a href="hello-node/install.sh" class="code-link"&gt;install.sh&lt;/a&gt;&lt;pre&gt;&lt;code&gt;mkdir ~/NodeLibs
cd ~/NodeLibs
git clone git://github.com/creationix/node-router.git
git clone git://github.com/creationix/haml-js.git
git clone git://github.com/creationix/proto.git
mkdir ~/.node_libraries
cd ~/.node_libraries
ln -s ~/NodeLibs/*/lib/* ./
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;
&lt;p&gt;That's it for now, this article was going to explain more, but it seems it got lost and fell through the cracks. Hopefully this will help you get started working with node.JS, it's a blast!.&lt;/p&gt;</description>
<pubDate>Mon Mar 22 2010 15:55:41 GMT+0000 (UTC)</pubDate>
</item>
<item>
<title>Facebook Connect with Node</title>
<category></category>
<author>[email protected] (Dominiek ter Heide)</author>
<guid>http://howtonode.org/facebook-connect</guid>
<link/>http://howtonode.org/facebook-connect
<description>&lt;p&gt;A big part of building a new web application is repurposing common patterns, one such pattern is the ability for users to sign in and out. One way of solving this quickly is by using Facebook Connect. &lt;/p&gt;
&lt;h2&gt;Background&lt;/h2&gt;
&lt;p&gt;Unlike some APIs, the Facebook API is very Javascript friendly, but unfortunately it can be very time consuming to go through the maze of misdirected Facebook documentation. So in order to make Facebook integration quick and easy, I've wrapped a lot of under-the-hood code into a plugin called &lt;a href="http://github.com/dominiek/node-facebook"&gt;node-facebook&lt;/a&gt;. This plugin also provides examples and routines to get your Facebook Canvas application running quickly with Node, however, this article will focus on the FB Connect part.&lt;/p&gt;
&lt;blockquote&gt;
&lt;p&gt;Facebook's developer tools are increasingly going into the direction of more Javascript on the client-side. I also have a strong preference of offloading certain logic to the client-side. This article will also attempt to follow &lt;a href="http://synaptify.com/?p=613702"&gt;that direction&lt;/a&gt;.&lt;/p&gt;
&lt;/blockquote&gt;
&lt;h2&gt;Communication&lt;/h2&gt;
&lt;p&gt;As you can see in this totally unnecessary diagram, most of the integration takes place on the client-side:&lt;/p&gt;
&lt;p&gt;&lt;img src="http://github.com/dominiek/node-facebook/raw/master/doc/communication.png" alt="Awesome Diagram" title="Awesome Diagram" /&gt;&lt;/p&gt;
&lt;h2&gt;Dependencies&lt;/h2&gt;
&lt;p&gt;&lt;em&gt;Note: For this article I've been using NodeJS version 0.1.31 and Express version 0.7.1&lt;/em&gt;&lt;/p&gt;
&lt;p&gt;You need to install both &lt;a href="http://nodejs.org"&gt;NodeJS&lt;/a&gt; and the &lt;a href="http://github.com/visionmedia/express"&gt;Express Web Framework&lt;/a&gt;. Assuming you've installed NodeJS, you can easily include express into your Git project by adding a submodule:&lt;/p&gt;
&lt;pre&gt;&lt;code&gt;mkdir -p lib/support
git submodule add git://github.com/visionmedia/express.git lib/support/express
cd lib/support/express
git submodule init
git submodule update
&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;Second, you need to include &lt;a href="http://github.com/brainfucker/hashlib"&gt;Hashlib&lt;/a&gt; into your project and compile it. Hashlib is a library that provides cryptographic routines like MD5:&lt;/p&gt;
&lt;pre&gt;&lt;code&gt;git submodule add git://github.com/brainfucker/hashlib.git lib/support/hashlib
cd lib/support/hashlib
make
&lt;/code&gt;&lt;/pre&gt;
&lt;h2&gt;1. Registering your Facebook Application&lt;/h2&gt;
&lt;p&gt;In order to use Facebook Connect, you need to &lt;a href="http://facebook.com/developer"&gt;register a new Facebook application&lt;/a&gt; and set the FB Connect URL to the root of your application:&lt;/p&gt;
&lt;p&gt;&lt;img src="http://github.com/dominiek/node-facebook/raw/master/doc/register_application.png" alt="Setting your FB Connect URL" title="Setting your FB Connect URL" /&gt;&lt;/p&gt;
&lt;h2&gt;2. Setting up your Project&lt;/h2&gt;
&lt;p&gt;For Facebook integration you need to place these three files into your project folder:&lt;/p&gt;
&lt;ol&gt;
&lt;li&gt;&lt;a href="http://github.com/dominiek/node-facebook/raw/master/lib/facebook.js"&gt;facebook.js&lt;/a&gt; - plugin for the Express framework - to be placed in /lib&lt;/li&gt;
&lt;li&gt;&lt;a href="http://github.com/dominiek/node-facebook/raw/master/lib/jquery.facebook.js"&gt;jquery.facebook.js&lt;/a&gt; - a simple jQuery plugin to interface with the &lt;a href="http://wiki.developers.facebook.com/index.php/JavaScript_Client_Library"&gt;Facebook JS library&lt;/a&gt; - to be placed in /public/javascripts&lt;/li&gt;
&lt;li&gt;&lt;a href="http://github.com/dominiek/node-facebook/raw/master/examples/fb_iframe/public/xd_receiver.htm"&gt;xd_receiver.htm&lt;/a&gt; - used by Facebook for opening up a &lt;a href="http://wiki.developers.facebook.com/index.php/Cross_Domain_Communication_Channel"&gt;Cross-domain Communication Channel&lt;/a&gt; - to be placed in /public&lt;/li&gt;
&lt;/ol&gt;
&lt;p&gt;After adding the dependencies and placing these files, your directory structure should look like this:&lt;/p&gt;
&lt;pre&gt;&lt;code&gt;myproject
|-- app.js /* new file */
|-- lib
| |-- support
| | |-- express
| | `-- hashlib
| |-- facebook.js
`-- public
|-- index.html /* new file */
|-- xd_receiver.htm
`-- javascript
`-- jquery.facebook.js
&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;To make our application work, we only need to implement two files: index.html and app.js. That's right, we're only using AJAX calls and static files.&lt;/p&gt;
&lt;h2&gt;3. In the Browser&lt;/h2&gt;
&lt;p&gt;The provided jQuery plugin provides the following functions that we'll be using:&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;&lt;strong&gt;fbInit&lt;/strong&gt; - initialize the JS lib and set up the cross-communication channel&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;fbConnect&lt;/strong&gt; - invoke the connect procedure and to synchronize sessions and profile information with our backend&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;fbLogout&lt;/strong&gt; - logout from both the Facebook Application and our NodeJS application&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;fbIsAuthenticated&lt;/strong&gt; - check whether a user is logged in or not&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;First we start out with a simple skeleton that loads jQuery and the Facebook JS library. Please note that you need the div named &lt;em&gt;fb-root&lt;/em&gt; right after the body tag for Facebook's lib to work:&lt;/p&gt;
&lt;pre&gt;&lt;code&gt;&amp;lt;html&amp;gt;
&amp;lt;head&amp;gt;
&amp;lt;script type="text/javascript" src="http://ajax.googleapis.com/ajax/libs/jquery/1.3.2/jquery.min.js"&amp;gt;&amp;lt;/script&amp;gt;
&amp;lt;script type="text/javascript" src="/javascripts/jquery.facebook.js"&amp;gt;&amp;lt;/script&amp;gt;
&amp;lt;/head&amp;gt;
&amp;lt;body&amp;gt;
&amp;lt;div id="fb-root"&amp;gt;&amp;lt;/div&amp;gt;
&amp;lt;script type="text/javascript" src="http://static.ak.connect.facebook.com/js/api_lib/v0.4/FeatureLoader.js.php"&amp;gt;&amp;lt;/script&amp;gt;
&amp;lt;/body&amp;gt;
&amp;lt;/html&amp;gt;
&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;Now let's implement a basic UI:&lt;/p&gt;
&lt;div class="snippet"&gt;&lt;a href="facebook-connect/index.html" class="code-link"&gt;index.html&lt;/a&gt;&lt;pre&gt;&lt;code&gt;&amp;lt;!DOCTYPE html PUBLIC &amp;quot;-//W3C//DTD XHTML 1.0 Transitional//EN&amp;quot;
&amp;quot;http://www.w3.org/TR/xhtml1/DTD/xhtml1-transitional.dtd&amp;quot;&amp;gt;
&amp;lt;html xmlns=&amp;quot;http://www.w3.org/1999/xhtml&amp;quot;&amp;gt;
&amp;lt;head&amp;gt;
&amp;lt;script type=&amp;quot;text/javascript&amp;quot; src=&amp;quot;http://ajax.googleapis.com/ajax/libs/jquery/1.3.2/jquery.min.js&amp;quot;&amp;gt;&amp;lt;/script&amp;gt;
&amp;lt;script type=&amp;quot;text/javascript&amp;quot; src=&amp;quot;/javascripts/jquery.facebook.js&amp;quot;&amp;gt;&amp;lt;/script&amp;gt;
&amp;lt;script type=&amp;quot;text/javascript&amp;quot;&amp;gt;
$(document).ready(function () {
$.fbInit('FACEBOOK_API_KEY');
// FB Connect action
$('#fb-connect').bind('click', function () {
$.fbConnect({'include': ['first_name', 'last_name', 'name', 'pic']}, function (fbSession) {
$('.not_authenticated').hide();
$('.authenticated').show();
$('#fb-first_name').html(fbSession.first_name);
});
return false;
});
// FB Logout action
$('#fb-logout').bind('click', function () {
$.fbLogout(function () {
$('.authenticated').hide();
$('.not_authenticated').show();
});
return false;
});
// Check whether we're logged in and arrange page accordingly
$.fbIsAuthenticated(function (fbSession) {
// Authenticated!
$('.authenticated').show();
$('#fb-first_name').html(fbSession.first_name);
}, function () {
// Not authenticated
$('.not_authenticated').show();
});
});
&amp;lt;/script&amp;gt;
&amp;lt;/head&amp;gt;
&amp;lt;body&amp;gt;
&amp;lt;div id=&amp;quot;fb-root&amp;quot;&amp;gt;&amp;lt;/div&amp;gt;
&amp;lt;script type=&amp;quot;text/javascript&amp;quot; src=&amp;quot;http://static.ak.connect.facebook.com/js/api_lib/v0.4/FeatureLoader.js.php&amp;quot;&amp;gt;&amp;lt;/script&amp;gt;
&amp;lt;div id=&amp;quot;my-account&amp;quot;&amp;gt;
&amp;lt;div class=&amp;quot;authenticated&amp;quot; style=&amp;quot;display: none&amp;quot;&amp;gt;
Hi there &amp;lt;span id=&amp;quot;fb-first_name&amp;quot;&amp;gt;&amp;lt;/span&amp;gt;!
&amp;lt;a href=&amp;quot;#&amp;quot; id=&amp;quot;fb-logout&amp;quot;&amp;gt;Logout&amp;lt;/a&amp;gt;
&amp;lt;/div&amp;gt;
&amp;lt;div class=&amp;quot;not_authenticated&amp;quot; style=&amp;quot;display: none&amp;quot;&amp;gt;
&amp;lt;a href=&amp;quot;#&amp;quot; id=&amp;quot;fb-connect&amp;quot;&amp;gt;Connect with Facebook&amp;lt;/a&amp;gt;
&amp;lt;/div&amp;gt;
&amp;lt;/div&amp;gt;
&amp;lt;/body&amp;gt;
&amp;lt;/html&amp;gt;
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;
&lt;h2&gt;4. On the Server&lt;/h2&gt;
&lt;p&gt;The &lt;a href="http://github.com/visionmedia/express"&gt;Express&lt;/a&gt; plugin is initialized like any other plugin in the environment configuration routine, but takes your Facebook API key and Secret as mandatory initialization arguments:&lt;/p&gt;
&lt;pre&gt;&lt;code&gt;use(require('facebook').Facebook, {
apiKey: 'FACEBOOK_API_KEY',
apiSecret: 'FACEBOOK_API_SECRET'
})
&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;Next we need to implement 3 AJAX actions to make jquery.facebook.js work:&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;&lt;strong&gt;GET /fbSession&lt;/strong&gt; - Is the current user logged in? Or is there a cookie/param present I can use to authenticate?&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;POST /fbSession&lt;/strong&gt; - Update additional information about the user (name, picture, etc)&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;POST /fbLogout&lt;/strong&gt; - Called after logout from the Facebook Application took place&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;Here is an example Express application that uses no persistent storage:&lt;/p&gt;
&lt;div class="snippet"&gt;&lt;a href="facebook-connect/app.js" class="code-link"&gt;app.js&lt;/a&gt;&lt;pre&gt;&lt;code&gt;require.paths.unshift(__dirname + '/../../lib')
require.paths.unshift(__dirname + '/../../lib/support/express/lib')
require.paths.unshift(__dirname + '/../../lib/support/hashlib/build/default')
require('express')
require('express/plugins')
configure(function(){
use(MethodOverride)
use(ContentLength)
use(Cookie)
use(Session)
use(Logger)
use(require('facebook').Facebook, {
apiKey: 'FACEBOOK_API_KEY',
apiSecret: 'FACEBOOK_API_SECRET'
})
set('root', __dirname)
})
// Called to get information about the current authenticated user
get('/fbSession', function(){
var fbSession = this.fbSession()
if(fbSession) {
// Here would be a nice place to lookup userId in the database
// and supply some additional information for the client to use
}
// The client will only assume authentication was OK if userId exists
this.contentType('json')
this.halt(200, JSON.stringify(fbSession || {}))
})
// Called after a successful FB Connect
post('/fbSession', function() {
var fbSession = this.fbSession() // Will return null if verification was unsuccesful
if(fbSession) {
// Now that we have a Facebook Session, we might want to store this new user in the db
// Also, in this.params there is additional information about the user (name, pic, first_name, etc)
// Note of warning: unlike the data in fbSession, this additional information has not been verified
fbSession.first_name = this.params.post['first_name']
}
this.contentType('json')
this.halt(200, JSON.stringify(fbSession || {}))
})
// Called on Facebook logout
post('/fbLogout', function() {
this.fbLogout();
this.halt(200, JSON.stringify({}))
})
// Static files in ./public
get('/', function(file){ this.sendfile(__dirname + '/public/index.html') })
get('/xd_receiver.htm', function(file){ this.sendfile(__dirname + '/public/xd_receiver.htm') })
get('/javascripts/jquery.facebook.js', function(file){ this.sendfile(__dirname + '/public/javascripts/jquery.facebook.js') })
run()
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;
&lt;blockquote&gt;
&lt;p&gt;The verification of Facebook data by the server-side is done by using the Application Secret and the signature that's sent along with the data. First, all parameters and cookies are put together in one string and then the Application Secret is appended to it. The MD5 hash of this string should match the signature that's included. &lt;a href="http://wiki.developers.facebook.com/index.php/Verifying_The_Signature"&gt;more about verifying the signature&lt;/a&gt;&lt;/p&gt;
&lt;/blockquote&gt;
&lt;p&gt;In any subsequently added action, you can access the Facebook Session simply like this:&lt;/p&gt;
&lt;pre&gt;&lt;code&gt;get('/hello', function () {
var fbSession = this.fbSession()
return 'Hello ' + ' user ' + fbSession.userId + '!';
})
&lt;/code&gt;&lt;/pre&gt;
&lt;h2&gt;6. Further Development&lt;/h2&gt;
&lt;p&gt;In this article we went into the direction of putting a lot of UI flow and controller logic into the browser. This can be quite counter-intuitive. As a Rails-programmer and former RJS lover, I can attest to that. However, while there are still remaining issues like SEO and accessibility, this approach allows the server to really focus on data modelling/routing and has numerous scaling benefits.&lt;/p&gt;
&lt;p&gt;All examples in this article and more can be found on the &lt;a href="http://github.com/dominiek/node-facebook"&gt;node-facebook repository&lt;/a&gt; I created. If you run into any obstacles, feel free to &lt;a href="http://dominiek.com/"&gt;contact me&lt;/a&gt; or fork the code. I hope to soon write a similar plugin for Twitter's OAUTH based login.&lt;/p&gt;
&lt;h2&gt;Appendix A: Facebook Troubleshooting Checklist&lt;/h2&gt;
&lt;p&gt;Debugging Facebook Application problems can be a real pain in the neck, here is a simple checklist distilled from many frustrating mind-cycles:&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;Are you sure xd_receiver.htm is in place and being accessed?&lt;/li&gt;
&lt;li&gt;Are you sure the &lt;div id="root"&gt;&lt;/div&gt; element is present in the body?&lt;/li&gt;
&lt;li&gt;If you are using Safari with iFrames, there are some &lt;a href="http://saizai.livejournal.com/897522.html"&gt;cookie hacks&lt;/a&gt; you need to do&lt;/li&gt;
&lt;li&gt;Are cookies being set successfully after FB connect?&lt;/li&gt;
&lt;li&gt;Are you sure you're using the correct API keys?&lt;/li&gt;
&lt;/ul&gt;</description>
<pubDate>Thu Mar 18 2010 22:00:00 GMT+0000 (UTC)</pubDate>
</item>
<item>
<title>What is "this"?</title>
<category></category>
<author>[email protected] (Tim Caswell)</author>
<guid>http://howtonode.org/what-is-this</guid>
<link/>http://howtonode.org/what-is-this
<description>&lt;p&gt;Most people that learn JavaScript are coming from a background in another language. This brings with it a view of how the world works that may be different from how it really works in JavaScript. For this and other reasons, JavaScript is often misunderstood. It's not entirely our fault, the language was designed to work like one thing (scheme-like), but look like another (c-like). This article will describe lexical scope and the "&lt;code&gt;this&lt;/code&gt;" variable and how to control them rather than be controlled by them when in coding JavaScript.&lt;/p&gt;
&lt;h2&gt;It's all about where you are.&lt;/h2&gt;
&lt;p&gt;In all programming languages, there is this idea of current scope and current context. In JavaScript we have a lexical scope and a current "&lt;code&gt;this&lt;/code&gt;" context.&lt;/p&gt;
&lt;p&gt;In JavaScript all new scopes are created through "&lt;code&gt;function&lt;/code&gt;" definitions. But contrary to other c-like languages, this is the &lt;em&gt;only&lt;/em&gt; way to make a new scope. For loops don't do it, if blocks don't do it, plain curly braces assuredly don't do it. This simplicity is both a blessing and a curse. First let's have a couple of examples to explain creating scopes.&lt;/p&gt;
&lt;p&gt;This is an example of global scope:&lt;/p&gt;
&lt;div class="snippet"&gt;&lt;a href="what-is-this/global.js" class="code-link"&gt;global.js&lt;/a&gt;&lt;pre&gt;&lt;code&gt;// Define a couple of global variables
var name = &amp;quot;Tim&amp;quot;;
var age = 28;
// Access one of them from the global scope
name;
&lt;/code&gt;&lt;/pre&gt;&lt;dl class="output"&gt;&lt;dt&gt;Output&lt;/dt&gt;&lt;dd&gt;&lt;div class="last-expression"&gt;=&amp;gt; 'Tim'&lt;/div&gt;&lt;/dd&gt;&lt;/dl&gt;&lt;/div&gt;
&lt;p&gt;This is an example of local scope:&lt;/p&gt;
&lt;div class="snippet"&gt;&lt;a href="what-is-this/local.js" class="code-link"&gt;local.js&lt;/a&gt;&lt;pre&gt;&lt;code&gt;// Create a couple of local variables in a function.
function newScope() {
var name = &amp;quot;tim&amp;quot;;
var age = 28;
}
// Try to access the local variables from the global scope
// This will cause an error.
name;
&lt;/code&gt;&lt;/pre&gt;&lt;dl class="error"&gt;&lt;dt&gt;Error&lt;/dt&gt;&lt;dd&gt;ReferenceError: name is not defined&lt;/dd&gt;&lt;/dl&gt;&lt;/div&gt;
&lt;h3&gt;Lexical Scope&lt;/h3&gt;
&lt;p&gt;Lexical scope is the key to making closures work. Here's a quote from wikipedia about closures and lexical scope:&lt;/p&gt;
&lt;blockquote&gt;
&lt;p&gt;In computer science, a closure is a first-class function with free variables that are bound in the lexical environment. Such a function is said to be "closed over" its free variables. A closure is defined within the scope of its free variables, and the extent of those variables is at least as long as the lifetime of the closure itself.&lt;/p&gt;
&lt;/blockquote&gt;
&lt;p&gt;So what does all that mean? Here's an example:&lt;/p&gt;
&lt;div class="snippet"&gt;&lt;a href="what-is-this/lexical.js" class="code-link"&gt;lexical.js&lt;/a&gt;&lt;pre&gt;&lt;code&gt;var sys = require('sys');
var name = &amp;quot;outer&amp;quot;;
function one() {
var name = &amp;quot;middle&amp;quot;;
var other = &amp;quot;findme&amp;quot;;
function two() {
var name = &amp;quot;inner&amp;quot;;
// Here `name` is &amp;quot;inner&amp;quot; and `other` is &amp;quot;findme&amp;quot;
sys.p({name: name, other: other});
}
two();
// Here `name` is &amp;quot;middle&amp;quot; and `other` is &amp;quot;findme&amp;quot;
sys.p({name: name, other: other});
}
one();
// Here `name` is &amp;quot;outer&amp;quot; and `other` is undefined.
sys.p({name: name});
sys.p({other: other});
&lt;/code&gt;&lt;/pre&gt;&lt;dl class="output"&gt;&lt;dt&gt;Output&lt;/dt&gt;&lt;dd&gt;{ name: 'inner', other: 'findme' }
{ name: 'middle', other: 'findme' }
{ name: 'outer' }
&lt;/dd&gt;&lt;/dl&gt;&lt;dl class="error"&gt;&lt;dt&gt;Error&lt;/dt&gt;&lt;dd&gt;ReferenceError: other is not defined&lt;/dd&gt;&lt;/dl&gt;&lt;/div&gt;
&lt;p&gt;Here we see that local variables in an inner scope can shadow variables by the same name in the outer scope. But from the outside, variables in the inside don't exist. Lexical scope is 100% based on the physical location of the variables in the nesting in the code. It doesn't matter what path you might take to get to the inner function. That's how closures are able to make inner variables usable.&lt;/p&gt;
&lt;div class="snippet"&gt;&lt;a href="what-is-this/closure.js" class="code-link"&gt;closure.js&lt;/a&gt;&lt;pre&gt;&lt;code&gt;var sys = require('sys');
// Make a function that returns a closure function.
function myModule() {
var name = &amp;quot;tim&amp;quot;, age = 28;
return function greet() {
return &amp;quot;Hello &amp;quot; + name + &amp;quot;. Wow, you are &amp;quot; + age + &amp;quot; years old.&amp;quot;;
}
}
// call `myModule` to get a closure out of it.
var greeter = myModule();
// Call the closure
greeter();
&lt;/code&gt;&lt;/pre&gt;&lt;dl class="output"&gt;&lt;dt&gt;Output&lt;/dt&gt;&lt;dd&gt;&lt;div class="last-expression"&gt;=&amp;gt; 'Hello tim. Wow, you are 28 years old.'&lt;/div&gt;&lt;/dd&gt;&lt;/dl&gt;&lt;/div&gt;
&lt;p&gt;The variables &lt;code&gt;name&lt;/code&gt; and &lt;code&gt;age&lt;/code&gt; are local to the &lt;code&gt;myModule&lt;/code&gt; function, but when we call &lt;code&gt;greeter&lt;/code&gt; from the global scope, it doesn't throw an error. This is because the &lt;code&gt;greet&lt;/code&gt; function has &lt;code&gt;name&lt;/code&gt; and &lt;code&gt;age&lt;/code&gt; in it's lexical scope and so they're accessible as if they were local variables. Basically the way variable lookup works is that it goes up scope by scope looking for a variable by the requested name.&lt;/p&gt;
&lt;h3&gt;The context of "&lt;code&gt;this&lt;/code&gt;"&lt;/h3&gt;
&lt;p&gt;In addition to the lexical scope. JavaScript adds another layer of locality through the special keyword "&lt;code&gt;this&lt;/code&gt;". This keyword looks and acts like any other javascript variable except that you can't modify it. It acts as a reference to the context object, and as an object, you can get to it's properties through normal dot or bracket notation. The magic is that the value of "&lt;code&gt;this&lt;/code&gt;" changes depending on what context your executing in. In most cases, the context is the receiver of the message. For example:&lt;/p&gt;
&lt;div class="snippet"&gt;&lt;a href="what-is-this/this.js" class="code-link"&gt;this.js&lt;span class="hash"&gt;#person&lt;/span&gt;&lt;/a&gt;&lt;pre&gt;&lt;code&gt;var Person = {
name: &amp;quot;Tim&amp;quot;,
age: 28,
greeting: function () {
return &amp;quot;Hello &amp;quot; + this.name + &amp;quot;. Wow, you are &amp;quot; + this.age + &amp;quot; years old.&amp;quot;;
}
};
Person.greeting();
&lt;/code&gt;&lt;/pre&gt;&lt;dl class="output"&gt;&lt;dt&gt;Output&lt;/dt&gt;&lt;dd&gt;&lt;div class="last-expression"&gt;=&amp;gt; 'Hello Tim. Wow, you are 28 years old.'&lt;/div&gt;&lt;/dd&gt;&lt;/dl&gt;&lt;/div&gt;
&lt;p&gt;Note that I was able to access &lt;code&gt;Person.name&lt;/code&gt; and &lt;code&gt;Person.age&lt;/code&gt; from within &lt;code&gt;Person.greeting&lt;/code&gt;. &lt;/p&gt;
&lt;h3&gt;"&lt;code&gt;this&lt;/code&gt;" is where it bites&lt;/h3&gt;
&lt;p&gt;The previous code almost looks like objects from other languages. But that's where it bites you. As the author of the &lt;code&gt;Person&lt;/code&gt; module, you have no assurance that "&lt;code&gt;this&lt;/code&gt;" will be the same as "&lt;code&gt;Person&lt;/code&gt;". For example, what if I wanted to store the greeting function somewhere else:&lt;/p&gt;
&lt;div class="snippet"&gt;&lt;a href="what-is-this/this.js" class="code-link"&gt;this.js&lt;span class="hash"&gt;#standalone&lt;/span&gt;&lt;/a&gt;&lt;pre&gt;&lt;code&gt;var greeting = Person.greeting;
greeting(); // Will get undefined for `this.name` and `this.age`
&lt;/code&gt;&lt;/pre&gt;&lt;dl class="output"&gt;&lt;dt&gt;Output&lt;/dt&gt;&lt;dd&gt;&lt;div class="last-expression"&gt;=&amp;gt; 'Hello undefined. Wow, you are undefined years old.'&lt;/div&gt;&lt;/dd&gt;&lt;/dl&gt;&lt;/div&gt;
&lt;p&gt;The problem here is that "&lt;code&gt;this&lt;/code&gt;" in the body of the greeting function is now the global object and not the &lt;code&gt;Person&lt;/code&gt; object. How about one more example just for fun:&lt;/p&gt;
&lt;div class="snippet"&gt;&lt;a href="what-is-this/this.js" class="code-link"&gt;this.js&lt;span class="hash"&gt;#dog&lt;/span&gt;&lt;/a&gt;&lt;pre&gt;&lt;code&gt;var Dog = {
name: &amp;quot;Alfred&amp;quot;,
age: 110,
greeting: Person.greeting
}
Dog.greeting(); // This will work and it will show the dog's data.
&lt;/code&gt;&lt;/pre&gt;&lt;dl class="output"&gt;&lt;dt&gt;Output&lt;/dt&gt;&lt;dd&gt;&lt;div class="last-expression"&gt;=&amp;gt; 'Hello Alfred. Wow, you are 110 years old.'&lt;/div&gt;&lt;/dd&gt;&lt;/dl&gt;&lt;/div&gt;
&lt;p&gt;The greeting function in Dog and the function in Person are &lt;strong&gt;the same&lt;/strong&gt; function. They're both references to the same object in memory. But depending on where it's called from, can change the value of "&lt;code&gt;this&lt;/code&gt;". Basically "&lt;code&gt;this&lt;/code&gt;" is whatever object comes before the dot in the call. That's why &lt;code&gt;Dog.greeting()&lt;/code&gt; uses &lt;code&gt;Dog&lt;/code&gt; as "&lt;code&gt;this&lt;/code&gt;" and &lt;code&gt;Person.greeting()&lt;/code&gt; uses &lt;code&gt;Person&lt;/code&gt;. When there is nothing before the function call, then the global object is used for "&lt;code&gt;this&lt;/code&gt;".&lt;/p&gt;
&lt;h3&gt;Taming "&lt;code&gt;this&lt;/code&gt;"&lt;/h3&gt;