luciotato / waitfor

Sequential programming for node.js, end of callback hell / pyramid of doom
MIT License
531 stars 29 forks source link

Adding wait.for to an express app #29

Closed blakemcbride closed 9 years ago

blakemcbride commented 9 years ago

Greetings,

Express uses the following code in bin/www to start the server:

var server = http.createServer(app);

I changed it to:

var server = http.createServer(
    function(req, res){
        console.log('req!');
        wait.launchFiber(app,req,res); //handle in a fiber, keep node spinning
    });

Is that correct?

The reason I ask is because later in the code, wait.for doesn't work unless I do a wait.launchFiber first. I thought if I did launchFiber when I created the server I wouldn't have to do it anywhere else.

Thanks!

Blake

luciotato commented 9 years ago

I guess your modification is not correct.

The reason wait.launchFiber didn't work at "http.createServer" is basically that It is not that magic!. ;)

wait.launchFiber starts executing the function as a fiber-generator until a "yield" (wait.for) is found, then wait.launchFiber execute the "yielded" value (a call to an async function), and links the "next" of the generator with the async callback(err,data), so when the async finishes and the callback is called, the fiber/generator "continues" after the var x =wait.for(...).

You should use wait.launchFiber to launch a function which will use wait.for() internally, i.e. a function which needs to call some async functions in order to achieve its goal.

what is "app" in your example? it is a function using wait.for internally? I'm not that familiar with Express, but I think "app" is not a function using wait.for internally.

Please use this example as guide: https://github.com/luciotato/waitfor#basic-usage-example-with-expressjs

luciotato commented 9 years ago

Are you modifying express source code? Check this example first: https://github.com/luciotato/waitfor#basic-usage-example-with-expressjs

blakemcbride commented 9 years ago

Hi. I did not change the express source code. The point of my misunderstanding is not what express does.

app is var app = express();

Your "Basic Usage Example with Express.js" shows:

app.get('/', function(req,res){

but express does:

var router = express.Router();
router.get('/', function(req,res){

The "get" comes from router and not "app". I followed that example using "router" instead and it does work. My real question has to do with the "Proper Use:" section. It says that I can call wait.for anywhere if I start the server in a fiber. That is what I am trying to do.

Thanks a lot for all the help!

Blake

luciotato commented 9 years ago

ok, glad its working now.

blakemcbride commented 9 years ago

Although my first problem is solved, the problem I describe in this thread is not. If you could help me, I would greatly appreciate it.

Please see the forth message in this thread.

Thank you so much!

Blake

luciotato commented 9 years ago

My real question has to do with the "Proper Use:" section. It says that I can call wait.for anywhere if I start the server in a fiber. That is what I am trying to do.

You cannot use wait.launchFiber to call createServer. You must use wait.launchFiber to handle every request. As in the example:

Proper use:

The ideal place to launch a fiber is when a request arrives, to handle it:

var server = http.createServer(
       function(req, res){
           console.log('req!');
           wait.launchFiber(handler,req,res); //handle in a fiber, keep node spinning
    }).listen(8000);

then, at function handler(req,res) and every function you call from there, you'll be able to use wait.for(ayncFn...

Let me expand the example to make it clearer:

function launchFiberForRequest(req, res){
           console.log('req!');
           wait.launchFiber(myHandler,req,res); //handle in a fiber, keep node spinning
           // return to listen for more requests
}

var server = http.createServer(launchFiberForRequest);
server.listen(8000);

Then you write function myHandler in which you can use wait.for...

If you like, you can put all of this in a function startServer, i.e.:

function startServer(port, myHandler){

     //helper function launchFiberForRequest
     function launchFiberForRequest(req, res){
           console.log('req!');
           wait.launchFiber(myHandler,req,res); //handle in a fiber, keep node spinning
           // return to listen for more requests
      }

      var server = http.createServer(launchFiberForRequest);
      server.listen(port);
      return server;
}
blakemcbride commented 9 years ago

In my express application, I changed bin/www (which gets fully created by express) from:

var server = http.createServer(app);
server.listen(port);

into:

var startServer = function(port, myHandler){

    //helper function launchFiberForRequest
    var launchFiberForRequest = function (req, res){
       console.log('req!');
        wait.launchFiber(myHandler,req,res); //handle in a fiber, keep node spinning
        // return to listen for more requests
    }
    var server = http.createServer(launchFiberForRequest);
    server.listen(port);
    return server;
};
var server = startServer(port, app);

It does not work. I see what you are doing and it makes sense. I just can't seem to translate that into an express application. Again, the app object is created by:

var app = require('../app');

../app.js is also generated by express but modified to setup routes, etc..

I can't seem to translate your node code into express code.

Thanks for all the help!

Blake

luciotato commented 9 years ago

Blake: that was just an example using node's http. It does not work with Express. To use express use this:

https://github.com/luciotato/waitfor#basic-usage-example-with-expressjs

That's the only way possible.

blakemcbride commented 9 years ago

Okay. Got it. Thanks!