Open Search

Using async methods in name spaced javascript

June 4, 2018 10:36 am
Categorised in:
Reading Time: 2 minutes

Spent an hour boggling my brain on this, so it’s one to write down. If you are namespacing your javascript functions using the module pattern you may run into an instance where you try to return an async value (i.e. from a json resource) and the value obviously returns immediately. So if you have something like this in your module file:

var staffList = ( function() {
 	function getStaffList(){
		var xmlhttp = new XMLHttpRequest();
		xmlhttp.onreadystatechange = function() {
			if (this.readyState == 4 && this.status == 200) {
				var x = JSON.parse(this.responseText);
				list = x;
				return x;
			}
		};
		xmlhttp.open("GET", "https://jsonplaceholder.typicode.com/posts/1", true);
		xmlhttp.send();
 	}
 	var list;
	return {
        	getList: function() {
         		if (list == undefined){
         			return getStaffList()
         		}else{
         			return list;
         		}
		}
	};
})();

And you are trying to call this elsewhere thusly:

var staffList = await cel_staffList.getList();
console.log(staffList);

Well, this is definitely going to fail. The function will return before we get the Json data from the server. So, we use a Promise and a async function to get the values correctly. What this also means and is where I kept failing is you have to wrap both your module callback as async AND wrap the callback you use elsewhere in an async function. This way everything waits correctly. So in practice this looks like this:


var cel_staffList = ( function() {
 	function getStaffList(){
 		return new Promise(resolve => {
			var xmlhttp = new XMLHttpRequest();
			xmlhttp.onreadystatechange = function() {
					if (this.readyState == 4 && this.status == 200) {
						var x = JSON.parse(this.responseText)
						resolve(x);
						list = x;
					}
			};
			xmlhttp.open("GET", "https://jsonplaceholder.typicode.com/posts/1", true);
			xmlhttp.send();
		});
 	}
 	var list;
 	return {
 	 	getList: async function() {
         	 	if (list == undefined){
         		 	return await getStaffList()
         	 	}else{
         		 	return list;
         	 	}
         	}
 	};  
})();

and then your callback later also looks like this now:

async function getList(){
	var staffList = await cel_staffList.getList();
	console.log(staffList);
}
getList();

and voila, we are returning the parsed json data. If the parsed data is already stored in the list variable we just return that and if not we tootle off to the server pick it up, parse it, assign (so we don’t go back each time) and return the value.

Pretty straight forward but it’s a Monday so my brain is still very fuzzy.

This joint was penned by @elmarko

Comments are closed here.