Both of the above code will result in a HTTP server listening on port 3000 and would render 'Hello World' for the index.
If you are wondering what on earth is function *(){} is they are harmony:generators and we can use ES6 on node today with node --harmony flag as of now.
Seeing this for the first time you might wonder where the hell are the req and res params!
The answer is the context. A Koa Context encapsulates node's request and response objects into a single object.
A Koa application is an object containing an array of middleware generator functions which are composed and executed in a stack-like manner upon request
So, for every request a new context is created:
1234567
app.use(function*(){this;// is the Contextthis.request;// is a koa Request.this.response;// is a koa Response.this.req;// nodejs request.this.res;// nodejs response.});
12345678910
// keys of this:['request','response','app','req','res','onerror','originalUrl','cookies','accept']
If we were to re-rewrite Koa hello world example with route it would be like:
Enough of hello-world, let's dig into the real power of generators in Koa!
With the help of ES6 generators it's uber easy and intuitive, have a look at the below example straight from Koa docs!
In the code above each yield next will make the to control to flow "downstream" from the "upstream" and finally where there are no more middlewears left the stack will unwind.
It's as good as the generator suspends and passes the flow to the downstream and then resumes.
The flow is like mw1->mw2->mw3 and backwards mw3->mw2->mw1
If you had cascaded multiple middlewares in Express which uses Connect's implementation which simply passes control through series of functions until one returns, which can get really messy with callback hell!
About 400 days ago I had blogged about live reload with grunt which explained about auto refreshing the browser on any change that occurs on the file that is being observed.
Here I would like to talk about a simple way to launch the browser from a node webserver.
Why do you need that? :
Because we are lazy!
For quick demos.
Quick Testing.
Less of manual work.
Let's see the code!:
1234567891011
varhttp=require('http'),open=require('open'),server;server=http.createServer(function(req,res){res.writeHead(200,{'Content-Type':'text/plain'});res.end('Hello World\n');});server.listen(1337,'127.0.0.1',function(){console.log('Launching the browser!');open('http://127.0.0.1:1337');});
The only dependency is : open which opens a file or uri with the users preferred application (browser, editor, etc), cross platform. [ npm install open ]
In the node API server.listen(port, [host], [backlog], [callback]) the last parameter callback will be added as an listener for the listening event, which is useful in identifying that the server is up and it's the right time to launch the browser!
Python datasets:dataset databases for lazy people! Bumped into this project that provides a simple abstraction layer removes most direct SQL and an export mechanism to export data in JSON or CSV formats.
Installing datasets via pip would be straight forward : pip install dataset
Why datasets?
Say if you have opted to use sqlite, the below is how normal operations would look like:
1234567891011121314151617181920212223242526
importsqlite3# open connection and get a cursorconn=sqlite3.connect(':memory:')c=conn.cursor()# create schema for a new tablec.execute('CREATE TABLE IF NOT EXISTS sometable (name, age INTEGER)')conn.commit()# insert a new rowc.execute('INSERT INTO sometable values (?, ?) ',('John Doe',37))conn.commit()# extend schema during runtimec.execute('ALTER TABLE sometable ADD COLUMN gender TEXT')conn.commit()# add another rowc.execute('INSERT INTO sometable values (?, ?, ?) ',('Jane Doe',34,'female'))conn.commit()# get a single rowc.execute('SELECT name, age FROM sometable WHERE name = ?',('John Doe',))row=list(c)[0]john=dict(name=row[0],age=row[1])
Last year I wrote about Hitchhikers guide to npm and node-grunt but a long awaited post was to write something about Yeoman a project which I'm closely associated from inception.
This post shall be demonstrating the sheer power of Yeoman in creating and maintaining node packages.
This generator helps you to create a node.js module including nodeunit unit tests and is based of grunt-init-node, authored by the
magnificent GruntJS team.
Let's get started :
First up, if you still haven't installed Yeoman, please go through the Gettng-Started wiki!
Assuming you have got Yeoman up and running, let's paw at node generator!
1
npm install -g generator-node # Install the generator.
I shall call the sample node package as exmp
12
mkdir exmp && cd $_
yo node
Now the magic happens ;) You just need to fill in the required details and the project's scaffold.
123456789101112131415161718
The name of your project shouldn't contain "node" or "js" and
should be a unique ID not already in use at search.npmjs.org.
[?] Module Name: exmp
[?] Description: The best module ever.
[?] Homepage:
[?] License: MIT
[?] GitHub username:
[?] Author's Name:
[?] Author's Email:
[?] Author's Homepage:
create lib/exmp.js
create test/exmp_test.js
create .jshintrc
create .gitignore
create .travis.yml
create README.md
create Gruntfile.js
create package.json
Digging deeper, we can notice the below dir struct, along with node_modules:
That's it! Once you cook your logic you can just go ahead and publish the module to node repository, with npm publish give that you have registered and have done a npm adduser.
So, what are you waiting for?
BTW, this post is a product of the talk I delivered at Google Bangalore as a part of BangaloreJS, on can view bjs the demo app that was created during the talk.
M4 API MutationObservers can be used to observe mutations to the tree of nodes.
It is designed as a replacement for Mutation Events defined in the DOM3 Events specification.
All you get with it is:
1234
varobserver=newMutationObserver(callback);// Get the changes.observer.observe(target,options);// Observer the desired node with options.observer.disconnect();// Stop observing.observer.takeRecords();// Empty the record queue and returns what was in there.
List of options:
Check out a sample DEMO I made for fun, which load random images from different sources ;)
If you are from python or ruby school, you shall be familar with negative array index, like a[-1] will return the last element, a[-2] will return the second-to-last element and so on.
In javascript we can make use of negitve indices like:
Object.defineProperty has been very useful for defining new properties or modifying the existing ones.
But faced an intresting senario of redefining video element's src attribute.
123456789101112131415
// Let's create a video element.varvideo=document.createElement('video');varvideos={comedy:'',drama:''};//Some collection.// Let's try to redefine the src attr.Object.defineProperty(video,'src',{set:function(type){this.src=videos[type];}});video.src=comdey;// This must set src to comedy video.
But for much obvio recursion we get InternalError: too much recursion on FF and RangeError: Maximum call stack size exceeded on Chrome.
As I was looking for a backdoor, one my colleagues @sashvini suggested a trick using setAttribute as video element was a DOM node with IDL attributes and methods are exposed to dynamic scripts.
Vola! It worked.
1234567
Object.defineProperty(video,'src',{set:function(url){this.setAttribute('src',videos[index]);}});video.src=comedy;// Now works as expected :)
P.S : The real use case for this was more complicated, have taken a silly example just to prove this!
Hope this is useful and there maybe many other ways to do this, do tell me know if you are aware of one such! (:
The keyword let helps in defining variables scoped to a single block.
123456789101112131415
functionaboutme(){{letgfs=10;varwife=1;}console.log(wife);console.log(gfs);}// Let's invoke aboutmeaboutme();// Would result in :1ReferenceError:gfsisnotdefined.
gfs got a ReferenceEorror as it was in a block and declared with let, syntactically similar to var, but defines a variable in the current block. The above is a simple example, but let is more useful in creating closures in loops and works better than var.
GENERATORS :
Generators helps to build iterators, yield is not a keyword in ES6 so the syntax to declare a generator function is function* (){}
Let's see an example :
12345678910111213141516
function*Counter(){varn=0;while(1<2){yieldn;++n}}varCountIter=newCounter();CountIter.next()// Would result in { value: 0, done: false }// Again CountIter.next()¬//Would result in { value: 1, done: false }
The done attribute will be true once the generator has nothing more to yield. Interestingly a generator can also yield another generator! :)
PROXIES :
Proxies provide a meta-programming API, that helps the programmer to define primitive object behaviour using traps
123456789
varlife=Proxy.create({get:function(obj,value){returnvalue==="ans"?42:"Meh! Nothing like : "+value}});life.ans// Would return 42life.lol// Would return Meh! Nothing like lol.
The above can be extended to simulating __noSuchMethod__
Object.observe provides a runtime capability to observe changes to an object.
12345678910111213141516171819202122232425
>vartodos=["eat","code","code","sleep"];// Using Array.observe>Array.observe(todos,function(changes){console.log(changes);})>todos.pop()'sleep'>[{type:'splice',object:['eat','code','code'],index:3,removed:['sleep'],addedCount:0}]>todos.push("sleep")4>[{type:'splice',object:['eat','code','code','sleep'],index:3,removed:[],addedCount:1}]// Similarly with Object.observe>varobj={}>Object.observe(obj,function(changes){console.log(changes);})>obj.name="hemanth";'hemanth'>[{type:'new',object:{name:'hemanth'},name:'name'}]
COLLECTIONS (Maps and Sets) :
Map objects are simple key/value maps, but it is different when compared to Object :
Objects have default key/value pairs from prototype.
Keys of an Object are Strings, where they can be any value for a Map.
Keeping track of size for an Object is manual, but Maps have size attribute.
Set objects let you store unique values of any type, whether primitive values or object references, but we still can't iterate them in node :(
12345678910111213141516
>Object.getOwnPropertyNames(Set.prototype)['constructor','size','add','has','delete','clear']>Object.getOwnPropertyNames(Map.prototype)['constructor','size','get','set','has','delete','clear']varmyMap=newMap();myMap.set(NaN,"not a number");myMap.get(NaN);// "not a number"varmySet=newSet();vartodos=["eat","code","sleep","code","drink","code"]todos.forEach(function(t){mySet.add(t);})todos.length// 6mySet.size// 4
Say you have a site example.com running on jekyll and you want example.com/blog to also be served from the same jekyll setup, here is what you need to do :
cd ~/example.com -> Root dir.
cd _includes -> Add a blogskin.html that would contain all the required css and js.
cd _layouts and create a blog layout that each of your blog posts will use, don't forget to Included file 'blogskin.html' not found in _includes directory
mkdir blog -> This would be the index for example.com/blog and hence must contain the index.html static file, listing all the blog posts, similar to an index file that jekyll new would generate, have a layout: blog so that index and the blog posts look and feel remains in sync.
echo "permalink: /blog/:title.html" >> _config.yml -> This would be premalink format for your blog posts.
Now, a jekyll build && jekyll server must have example.com/blog serving your blog :-)
Hope this helps, not sure if a bash script to do this will help more, will decide after some feedback ;)
This was a part of my learning gained while preparing yeoman's team blog.
@GNUmanth good notes! Thanks for helping us get the setup right for yeoman.io.