0
votes

I know Javascript but very new to NodeJS. I want to reuse http request anywhere in my code, outside of server.js. Please take a look:

server.js


    var http = require('http');
    var mongodb = require('./db');
    var settings = require('./settings');
    var oauth = require('./oauth');

    //start mongodb connection
    mongodb.connect(function(error){
        if (error) console.error(error);
        else {
            //set db as mongodb client
            var db = mongodb.use();
            //start http server
            http.createServer(function(request,response){
                //set POST body
                request.body = '';
                request.on('error',function(error){
                    console.error(error);
                    response.statusCode = 404;
                    response.end();
                }).on('data',function(chunk){
                    request.body += chunk;
                }).on('end',function(){
                    //database and http server ready, start logic
                    //Now I want to "require" a file here, such as test.js and call "request.headers" to work
                });
            }).listen(settings.httpPort,function(){
                console.log('Server listening on '+settings.httpServer+':'+settings.httpPort);
            });
        }
    });

And now I want to require test.js which do the following thing
test.js


    console.log(request.headers);

Note: I don't want to use any framework like Express. I want to write my own things from scratch. Please help me, thank you so much.

1

1 Answers

1
votes

If I understand correctly, the problem seems to be this: You want to access the result of an asynchronous function (the HTTP request) in other modules. However, Node's require() is synchronous; there is no asynchronous require(). There are a few solutions to this, none of which will be unfamiliar if you know JavaScript.

The simplest solution is to wrap your server.js module in a function that takes a callback. Then, call the callback once the request is available, like so:

// server.js
'use strict';

// ...

module.exports = function(callback) {

  // ...

  http.createServer((req, res) => {
    req.body = '';

    // Call end with error on error
    req.on('error', err => res.end(err));

    // Append chunks to body
    req.on('data', chunk => req.body += chunk);

    // Call callback here
    req.on('end', err => {
      // Call with error as first argument on error
      if (err) callback(err);
      // Call with request as second argument on success
      else callback(null, req);
    });

  }).listen(/*...*/);
  // ...
};

And in your test.js file:

// test.js
'use strict';

const server = require('./server');

// Do something with the request here.
server((err, req) => {
  if (err) console.error(err);
  else console.log(req.headers);
});

There is a problem with this approach. Every time you want to access the request, your server function will run all over again. What if you want to run the server once and then have access to the request as many times as you want?

Consider using Node's events module for this. In your server.js file, you can export an EventEmitter instance instead of a function. Emit appropriate events in that module, and then you can add listeners in any other module that needs access to the request. Your server.js file will look something like this:

// server.js
'use strict';

const EventEmitter = require('events');
const emitter = new EventEmitter();

// ...

http.createServer((req, res) => {
  req.body = '';
  req.on('error', err => res.end(err));
  req.on('data', chunk => req.body += chunk);

  // Emit events here:
  req.on('end', err => {
    // Emit 'error' event on error.
    if (err) emitter.emit('error', err);
    // Emit 'data' event on success.
    else emitter.emit('data', req);
  });
}).listen(/*...*/);

// ...

module.exports = emitter;

And in your test.js file:

// test.js
'use strict';

const server = require('./server');

// Do something on error event.
server.on('error', console.error);

// Do something on data event.
server.on('data', req => {
  console.log(req.headers);
});