Making Synchronous HTTP Requests in Node.js

Streams and asynchronous nature are things that makes Node so special and efficient. Although high chances you may never have to make a synchronous HTTP request in Node, yet knowing this will give you a better understanding of Node and Javascript.

Synchronous HTTP requests are possible in Node with the use of Javascript Promises, along with the concepts of async and await. This tutorial assumes you know a bit if these, but if not you can refer to these resources for understanding them :

Using Javascript Promises to Make HTTP Request

Consider sending a normal GET request. The request is sent to the server asynchronously, and the response is collected asynchronously.

// some code

http.get('http://www.usefulangle.com/api?api_key=554545', (response) => {
	let chunks_of_data = [];

	response.on('data', (fragments) => {
		chunks_of_data.push(fragments);
	});

	response.on('end', () => {
		let response_body = Buffer.concat(chunks_of_data);
		
		// response body
		console.log(response_body.toString());
	});

	response.on('error', (error) => {
		console.log(error);
	});
});

// some code

Now let us re-write the above code in a bit synchronous syntax, using Javascript Promises.

// some code

// define the promise
let request_call = new Promise((resolve, reject) => {
	http.get('http://www.usefulangle.com/api?api_key=554545', (response) => {
		let chunks_of_data = [];

		response.on('data', (fragments) => {
			chunks_of_data.push(fragments);
		});

		response.on('end', () => {
			let response_body = Buffer.concat(chunks_of_data);
			
			// promise resolved on success
			resolve(response_body.toString());
		});

		response.on('error', (error) => {
			// promise rejected on error
			reject(error);
		});
	});
});

// promise resolved or rejected
request_call.then((response) => {
	console.log(response);
}).catch((error) => {
	console.log(error);
});

// some code

The code looks a bit synchronous, but still executes asynchronously. To make it execute synchronously, we will need to use async and await.

Pausing Javascript Execution with async and await

The await operator can be placed before a Promise and makes Javascript to wait till the time promise is resolved or rejected. Until the time Promise is either resolved or rejected, code execution does not move forward and will keep "waiting".

// some code

// request_call is a Promise
await request_call;

// below code will not be executed till "request_call" Promise is resolved or rejected
// some code

await can only be used inside a async function. So in order to adjust the code, we will need to create a separate async function in which we will wait for the HTTP request to be made and full response to come.

// async function defined
async function makeSynchronousRequest() {
	try {
		// http_promise is a Promise
		// "response_body" will hold the response if the Promise is resolved 
		let response_body = await http_promise;
	}
	catch(e) {
		// if the Promise is rejected
		console.error(e);
	}
}

// async function called
makeSynchronousRequest();

The try .. catch block has been used to handle in case the Promise is rejected.

Complete Code

Combining the snippets from above, we have the complete code that allows us to make synchronous HTTP requests from Node.

const http = require('http');

// function returns a Promise
function getPromise() {
	return new Promise((resolve, reject) => {
		http.get('http://www.usefulangle.com/api?api_key=554545', (response) => {
			let chunks_of_data = [];

			response.on('data', (fragments) => {
				chunks_of_data.push(fragments);
			});

			response.on('end', () => {
				let response_body = Buffer.concat(chunks_of_data);
				resolve(response_body.toString());
			});

			response.on('error', (error) => {
				reject(error);
			});
		});
	});
}

// async function which will wait for the HTTP request to be finished
async function makeSynchronousRequest(request) {
	try {
		let http_promise = getPromise();
		let response_body = await http_promise;

		// holds response from server that is passed when Promise is resolved
		console.log(response_body);
	}
	catch(error) {
		// Promise rejected
		console.log(error);
	}
}

// some code 

// call the async function
makeSynchronousRequest();

// this code will be executed only when waiting for "makeSynchronousRequest" is finished
// some code
Making POST Requests in Node.JS
Making GET Requests in Node.JS