Sunday, 16 April 2017

Handling asynchronous URL parsing in NodeJS

I'm pretty new to Node.js and Javascript, so please forgive my confusion about the callback mechanism Bacchanalia.

My problem

I am building a simple Node.js application, which receives HTTP requests and sends their JSON body payload combined with their URL arguments as an input to a function. For the sake of learning I do not use any external framework or npm package.

So basically,

curl -i \
     -H "Content-Type: application/json" \
     -X POST \
     -d '{"jsonKey":"jsonValue"}' \
     'http://localhost:8888/y?urlKey=urlValue'

Should call an arbitrary function f with the parameters f({"jsonKey":"jsonValue", "urlKey":"urlValue"}).

Converting the URL args is pretty straightforward and requires no callbacks at all:

/* Parse the URL arguments */
function parseArguments(request) {
    var url_obj = url.parse(request.url, true);
    return url_obj.query;
}

The plot thickens when I try to add the JSON Payload to the returned value:

/* Parse the URL arguments and the JSON payload */
function parseArguments(request) {
    // URL Parameters 
    var arguments_as_object = url.parse(request.url, true).query;

    // JSON Payload, if any
    var body = [];
    request.on('data', function(chunk) {
        body.push(chunk);
    }).on('end', function() {
        body = Buffer.concat(body).toString();
        if (body) {
            body = JSON.parse(body);
            Object.assign(arguments_as_object, body);
        }
        console.log(new Date(), "Arguments with JSON are ", arguments_as_object);
    });

    console.log(new Date(), "Return value is ", arguments_as_object);
    return arguments_as_object;
}

The logs are:

2017-04-16T13:14:47.807Z 'Return value is ' { a: 'b' }
2017-04-16T13:14:47.826Z 'Arguments with JSON are ' { a: 'b', jsonKey: 'jsonValue' }

Unsurprisingly, parseArguments returns before the JSON parse is complete due to the asynchronous nature of javascript.

My question

How can I get the results of the asynchronous call and use them outside the function? Is there a way other than sending a callback function with all its arguments?

What have I tried

  • SFTW.
  • Using a callback instead of a return value. This seems to be the right way, but then I would have to send all the arguments of the callback to parseArguments, which would add a lot of unnecessary variables to its signature.


via Adam Matan

No comments:

Post a Comment