How could I make the 'request' module in Node.js load things in a synchronous fashion? The best advice I've seen is to somehow use the callback to get the function to not return itself until it is done. I am trying to use the 'request' function inline in code (things need to be processed based on that data that can't be placed in callbacks).
So how could I use the callback of the 'request' module to keep it from returning itself until it is finished with loading the resource?
What I'm doing is running a loop that downloads two values from an API, and then has to do some math based on those values. While the math could be done in callbacks... the loop would advance without the values it needs to perform the next operation. (So stopping the loop from advancing until the data is ready would solve the issue)
/* loop */ { /* URL Generation */ request( {url: base + u_ext}, function( err, res, body ) { var split1 = body.split("\n"); var split2 = split1[1].split(", "); ucomp = split2[1]; }); request( {url: base + v_ext}, function( err, res, body ) { var split1 = body.split("\n"); var split2 = split1[1].split(", "); vcomp = split2[1]; }); /* math which needs to be after functions get variables and before loop advances */ }
Synchronous request — (Default) Where the client blocks and waits for the result of the remote request before continuing execution. Asynchronous request — Where the client continues execution after initiating the request and processes the result whenever the AppServer makes it available.
Synchronous methods: Synchronous functions block the execution of the program until the file operation is performed. These functions are also called blocking functions. The synchronous methods have File Descriptor as the last argument.
HTTP is a synchronous protocol: the client issues a request and waits for a response. If you are using non-blocking (aka async) IO, the current thread of the client does not really have to wait, but can do other things (see above).
The short answer is: don't. (...) You really can't. And that's a good thing
I'd like to set the record straight regarding this:
NodeJS does support Synchronous Requests. It wasn't designed to support them out of the box, but there are a few workarounds if you are keen enough, here is an example:
var request = require('sync-request'), res1, res2, ucomp, vcomp; try { res1 = request('GET', base + u_ext); res2 = request('GET', base + v_ext); ucomp = res1.split('\n')[1].split(', ')[1]; vcomp = res2.split('\n')[1].split(', ')[1]; doSomething(ucomp, vcomp); } catch (e) {}
When you pop the hood open on the 'sync-request' library you can see that this runs a synchronous child process in the background. And as is explained in the sync-request README it should be used very judiciously. This approach locks the main thread, and that is bad for performance.
However, in some cases there is little or no advantage to be gained by writing an asynchronous solution (compared to the certain harm you are doing by writing code that is harder to read).
This is the default assumption held by many of the HTTP request libraries in other languages (Python, Java, C# etc), and that philosophy can also be carried to JavaScript. A language is a tool for solving problems after all, and sometimes you may not want to use callbacks if the benefits outweigh the disadvantages.
For JavaScript purists this may rankle of heresy, but I'm a pragmatist so I can clearly see that the simplicity of using synchronous requests helps if you find yourself in some of the following scenarios:
Test Automation (tests are usually synchronous by nature).
Quick API mash-ups (ie hackathon, proof of concept works etc).
Simple examples to help beginners (before and after).
Be warned that the code above should not be used for production. If you are going to run a proper API then use callbacks, use promises, use async/await, or whatever, but avoid synchronous code unless you want to incur a significant cost for wasted CPU time on your server.
In 2018, you can program the "usual" style using async
and await
in Node.js.
Below is an example, that wraps request callback in a promise and then uses await
to get the resolved value.
const request = require('request'); // wrap a request in an promise function downloadPage(url) { return new Promise((resolve, reject) => { request(url, (error, response, body) => { if (error) reject(error); if (response.statusCode != 200) { reject('Invalid status code <' + response.statusCode + '>'); } resolve(body); }); }); } // now to program the "usual" way // all you need to do is use async functions and await // for functions returning promises async function myBackEndLogic() { try { const html = await downloadPage('https://microsoft.com') console.log('SHOULD WORK:'); console.log(html); // try downloading an invalid url await downloadPage('http:// .com') } catch (error) { console.error('ERROR:'); console.error(error); } } // run your async function myBackEndLogic();
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With