James
James

Reputation: 110

How to do things synchronously in node

I know node is all about async stuff but I want to do things in serial mode as follows:

make api request > convert body xml to JSON.stringify > pass string to template.

request.get({url:url, oauth:oauth}, function(err, res, body){
    parseString(body, function(err, result){
        output = JSON.stringify(result);

        res.render('home', { title: 'Fantasy Home', 
                output: output });
    });
});

Now I want to do this in sequence, but with all the callbacks I'm confused.

res.render doesn't work nested inside callbacks because the res object doesn't exist. Having it outside won't work because it'll run before the callbacks execute so you'd get "undefined" for output.

There has to be a way to do things in sequential order. Why is everything a callback?? Why can't these functions just return a regular non-callback result?

How can I make this work?

Upvotes: 0

Views: 233

Answers (3)

borislemke
borislemke

Reputation: 9136

The others fail to mention why your res.render does not work. You probably have something like this:

app.get('/', function(req, res, next) { // You need the res here to .render

    request.get({url:url, oauth:oauth}, function(err, res, body){ // But you are using this res instead, which does not have the render method
        parseString(body, function(err, result){
            output = JSON.stringify(result);

            res.render('home', { title: 'Fantasy Home', 
                    output: output });
        });
    });
});

Read the comments in the code. So your solution is, use res.render from the request handler, rename res in the request.get callback to something else.

Upvotes: 1

Jitendra Khatri
Jitendra Khatri

Reputation: 774

JavaScript is single threaded if we use synchronous code then that will itself a big problem around response time (node.js) and all. Everything is implemented with callback fashion due to the benefit of event loop.

You can take a deep understanding of event loop : https://youtu.be/8aGhZQkoFbQ (Very good explaination)

You can use Promisification for the scenario you want to implement : http://bluebirdjs.com/docs/getting-started.html

request.get({url:url, oauth:oauth}, function(err, res, body) {
    // Note :: This is Promisified Function
    return parseString(body)
        .bind(this)
        .then(function(result) {
            output = JSON.stringify(result);

            res.render('home', {title: 'Fantasy Home', output: output });

            return true;
        })
        .catch(function(error)
        {
            // Error Handling Code Here
            // Then send response to client
        });
});

You can implement promisified function using the following approach

function parseString(body) {
    var Promise = require("bluebird");

    return new Promise(function(resolve,reject) {
        // Your Parsing Logic here

        if(is_parsed_successfully) {
            return resolve(parsed_data);
        }

        return reject(proper_err_data);
    })
}

Upvotes: 0

kWeglinski
kWeglinski

Reputation: 411

You should use middlewares, also promises is better thing to work with async in node, but I'll show you with callbacks. It is strongly suggested to not to block your thread with synchronous calls! Since node.js is single threaded. next() is an callback here so middleware won't allow execution of main route function (with res.render) until next() is called. You can pass as many middlewares as you wish.

app.use('/user/:id', middleware, (req, res) => {
    //here you'll find your data
    console.log(req.callData);
    res.render(view, req.callData);
}
middleware(req, res, next) => {
    dotheCall(dataToPass, (err, cb) => {
        req.callData = cb;
        // remember about handling errors of course!
        return next();
    })
}

Upvotes: 0

Related Questions