Monday, September 6, 2010

Getting Started Writing v0.5 Fab.js Apps

‹prev | My Chain | next›

Today, I hope to write my first version 0.5 fab.js app. In my (fab) game, I would like a resource that lists the status of all players currently in the game.

To start with, I create a very simple resource:
  (route, /^\/player_status/)
( undefined, { headers: { "Content-Type": "text/plain"} } )
( "hello\n" )
()
It bothers me that I do not understand the undefined thing. But checking it with curl, I see that this is working:
cstrom@whitefall:~$ curl http://localhost:4011/player_status -i
HTTP/1.1 200 OK
Content-Type: text/plain
Connection: keep-alive
Transfer-Encoding: chunked

hello
I will not be able to render my player_status inside function arguments—I need to iterate over all of my players. For that, I will need a v0.5 (fab) app. Walking before I run, I convert my "hello" arguments into the skeleton of my fab app:
function player_status(write) {
write = write(undefined, { headers: { "Content-Type": "text/plain"} } );
return function read() {
return write("hello\n");
};
}
A-ha! Now I see what the undefined argument is for—it is used to indicate that no body is being sent back in the response, just headers.

I replace my "hello" arguments with a call to player_status:
  (route, /^\/player_status/)
( player_status )
()
Then I start the app up and check out the response with curl:
cstrom@whitefall:~$ curl http://localhost:4011/player_status -i
curl: (52) Empty reply from server
There is no crash in my backend—no log output at all. Trying to access the game board is useless as well. It is as if the server is completely non-responsive, though in a non-crashy way.

It takes me quite a while to realize that I need to add an additional set of parentheses:
  (route, /^\/player_status/)
( player_status )
()
()
One set of parentheses finishes the player_status chain, the other completes the route chain. That is new to v0.5 and will take a bit of getting used to. Actually, no it won't. I think I have learned my lesson at this point.

Except...

When I try to convert player_status to dynamically return the list of players, I hit a problem. It seems as though the function is only evaluated at compile time, making it of little value for describing player statuses. Ugh.

I end up fiddling quite a bit and return to the player_status call without the trailing parentheses:
  (route, /^\/player_status/)
( player_status )
()
I then fake an upstream app from which player_status can read:
function player_status(write) {
write = write(undefined, { headers: { "Content-Type": "text/plain"} } );

return write(function(write) {
players.all(function(list) {
list.forEach(function(player) {
write = write(player._id + "\n");
});
return write();
}
);
});
That works from curl:
cstrom@whitefall:curl http://localhost:4011/player_status -i
HTTP/1.1 200 OK
Content-Type: text/plain
Connection: keep-alive
Transfer-Encoding: chunked

bob
But, I have an uncaught exception in my backend code:
Caught exception: TypeError: undefined is not a function
at CALL_NON_FUNCTION (native)
at Server.<anonymous> (/home/cstrom/.node_libraries/fab/index.js:78:8)
at Server.<anonymous> (/home/cstrom/.node_libraries/.npm/faye/0.5.2/package/faye-node.js:1819:22)
at Server.emit (events:33:26)
at HTTPParser.onIncoming (http:830:10)
at HTTPParser.onHeadersComplete (http:87:31)
at Stream.ondata (http:762:22)
at IOWatcher.callback (net:494:29)
at node.js:764:9
Sadly, I have to call it a night there. Up tomorrow: figure out where my disconnect lies.


Day #218

No comments:

Post a Comment