I "code" about bots & algos. Write about: Web3 Dev, DeFI, on/off-chain footprints, AI, NFTs & any novel edge I find...


I "code" about bots & algos. Write about: Web3 Dev, DeFI, on/off-chain footprints, AI, NFTs & any novel edge I find...
Share Dialog
Share Dialog

Subscribe to QuantArcane

Subscribe to QuantArcane
<100 subscribers
<100 subscribers
In this third part of our three-part series, we will delve into the evolution of the JavaScript language in the context of asynchronous programming. If you wish to:
Let's begin with the following scenario: Suppose we have a method called "getCapitals" that utilizes an external API to fetch world capitals. How can we return the results from the "getCapitals" method without halting our entire system while waiting for the capitals to be fetched?
In a synchronous approach, we would simply wait for the capitals to be fetched, effectively blocking our program, and then use the "return" statement with the fetched data.
In an asynchronous approach, the first method we will explore is using the callback pattern.

const callbackFunction = function (result) {
console.log(result);
}
const fakeCapitals = getCapitalsFake(callbackFunction);
console.log("Continue doing some other work that does not depend on the capitals");
On the left (in “app.js” file)
I define a callback function that, when called, prints the capitals to the console.
then I just call the “requests.js“ getCapitals function passing in the callback function to be called with the fetched data.
const getCapitalsFake = (callbackFunction) => {
setTimeout(() => {
const data = "waiting 3 seconds for data to arrive...";
callbackFunction(data);
}, 3000)
}
On the right (in “requests.js” file) the GetCapitals function:
receives the callback function passed in as a parameter.
it makes a http request to the API in order to fetch the data
defines an inner event listener that listens when the data is ready
the method finishes its execution and gives back control to app.js to execute other code.
Only once the data arrives, the event listener triggers and from within the listener we call the callback function from “app.js” received as param, passing it the result data.
Above I excluded all the boilerplate code of making the http request and listening for the result for brevity. Here is the actual code:
const getCapitals = (callback) => {
const request = new XMLHttpRequest()
request.addEventListener('readystatechange', (e) => {
if (e.target.readyState === 4 && e.target.status === 200) {
const data = JSON.parse(e.target.responseText);
console.log(data)
callback(undefined, data.map(d => d.capital).flat());
} else if (e.target.readyState === 4) {
callback('An error has taken place', undefined);
}
});
request.open('GET', 'https://restcountries.com/v3.1/all?fields=capital');
request.send();
}
And here is the code that calls the getCapitals method. Please note I used an anonymous arrow function as parameter instead of declaring the callback separately:
getCapitals((error, capitals) => {
if (error) {
console.log(`Error: ${error}`)
} else {
console.log(capitals)
}
});
Promises in JS are like Tasks in C#. To create a new promise we use its constructor that expects two callback functions as parameters. One that should be called on success and one on failure:
const myPromise = new Promise((resolve, reject) => {
setTimeout(() => {
const currentSeconds = new Date().getSeconds();
if (currentSeconds % 2 === 0) {
resolve("I am the data from the API endpoint");
}
else {
reject("I am an error, the API endpoint was down");
}
}, 2000)
});
In order to get the result back from a promise we use “then”. then is a method on the Promise object and it requires two functions as parameters:
a function that will be called when the Promise will be resolved with the data
a function that will be called when the Promise will be rejected with the error
myPromise.then((data) => {
console.log(data);
}, (err) => {
console.log(err);
})
in order to allow the promise access some data we can wrap a function around it that returns the promise like so:
const getPromiseFunction = (seedNumber) => {
return new Promise((resolve, reject) => {
//code excluded for brevity
});
Or better, simplify the syntax further by removing the “{} and return” since “getPromiseFunction” is a function that receives a number as param and returns a promise.
const getPromiseFunction = (seedNumber) => new Promise((resolve, reject) => {
setTimeout(() => {
const currentSeconds = new Date().getSeconds() + seedNumber;
if (currentSeconds % 2 === 0) {
resolve("I am the data from the API endpoint");
}
else {
reject("I am an error, the API endpoint was down");
}
}, 2000)
});
const myPromise2 = getPromiseFunction(3)
.then((data) => {
console.log(data);
}, (err) => {
console.log(err);
})
Now that we know what a promise is, we can use fetch API (which returns a promise) for making requests, instead of the low level "XMLHttpRequest”.
In our requests.js I will add the following method:
const getCountryByCode = (code) => {
const url = `https://restcountries.com/v3.1/alpha/${code}`;
return fetch(url).then((response) => {
if (response.status === 200) {
return response.json(); // RETURNS ANOTHER PROMISE
} else {
throw new Error("Unable to fetch country");
}
});
}
And in our “app.js“ I can get the result by calling the method as such:
getCountryByCode("US").then((data) => {
console.log(data);
}).catch((err) => {
console.log(`Error: ${err}`);
})
Now let’s break down the code.
Fetch returns a promise, so instead of doing “const getCountryByCode = (code) => new Promise()“ I can do directly “const getCountryByCode = (code) => fetch()“.
Going further, you can see that I already called “then” once on fetch. So instead of the promise returned by fetch I’m actually returning the promise returned by “response.json()”. This returns a promise with the response data. If something goes wrong I throw the error to be caught down the line.

Further, on the calling side I am calling “then” again on the response data promise in order to get the actual data from the response.
If any error occurs on any of the two “then“ (the one on “fetch” and the one on “getCountryByCode“) the attached “catch” will catch and log the error.
This is called chaining and is one of the biggest advantages that promises offer. Let’s further explore it.
Going back to our first API call example where we used the callback pattern, imagine you have a scenario where you need to fetch a country code by its name, then from the result you use the country code to fetch it’s capital, and then you would use the capital to fetch it’s population. Using the callback pattern would result in a hard to read, hard to maintain and error prone multi-nested code that’s often referred to as “callback hell”. By returning a promise instead of nesting a callback function you achieve promise chaining and avoid this callback hell.
We will first look at an example of a square function returning a promise. The function squares a number and takes 1 second to execute (imagine it’s part of a different API and data has to be fetched). We will square the result three times:
const squareNumber = (num) => new Promise((resolve, reject) => {
setTimeout(()=>{
typeof num === "number" ? resolve(num * num) : reject("Number not provided");
}, 1000)
})
This approach is close to the callback hell that you would be forced to do with callback pattern:
squareNumber(10).then((data) => {
squareNumber(data).then((data) => {
squareNumber(data).then((data) => {
console.log(data);
}, (err) => {
console.log(err);
})
}, (err) => {
console.log(err);
})
}, (err) => {
console.log(err);
})
But with promises instead of resolving on the spot with “then” we can choose to simply call the function and let it return the promise:
squareNumber(10).then((data) => {
return squareNumber(data)
}).then((data) => {
return squareNumber(data)
}).then((data) => {
console.log(data);
}).catch((err) => {
console.log(err)
})

Returning a promise from another promise it's called chaining.
Now let’s use a real world example. I will use the getCountryByCode defined earlier and also add a new request getCountriesByLanguage:
const getCountriesByLanguage = (language) => fetch(`https://restcountries.com/v3.1/lang/${language}`).then((response) => {
if (response.status === 200) {
return response.json();
} else {
throw new Error("Unable to fetch countries");
}
})
Now I will chain the two calls together:
first get a country by code, then search into the object and get the country’s first language
then use the language to get all countries that use the language fetched earlier as their first language.
getCountryByCode("US").then((country) => {
const language = Object.values(country[0].languages)[0];
return getCountriesByLanguage(language);
}).then((countries) => {
console.log(countries.map(i => i.name).map(i => i.official));
}).catch((err) => {
console.log(`Error: ${err}`);
})
.Net devs rejoice! Yet another feature borrowed from C#, which makes my life a lot easier in working with JavaScript!
Microsoft first introduced async/await pattern in C# 5.0 back in 2011-2012, and was adopted by several programming languages. And rightfully so because this was one of the greatest contributions to asynchronous programming.
Let’s explore how async/await builds on promises (Tasks in C#) and makes our code a whole lot easier to work with.
Below is a regular function that returns a string:
const someFunction = () => {
return "some text";
}
console.log(someFunction()); // prints: some text
and this is what happens when I make the function async:
const someFunctionAsync = async () => {
return "some other text";
}
console.log(someFunctionAsync()); // prints: Promise { 'some other text' }
It will make the function return a promise instead of the string itself

We can get the string by resolving the promise like we always do:
someFunctionAsync().then((data) =>
console.log(data)
).catch((err) =>
console.log(err)
);
Now in order to demonstrate await, do you remember our squareNumber function that returned a promise? We will call that in our function again three times passing in the result and see how async/await compares to promise chaining:
const someOtherFunctionAsync = async () => {
const firstSqare = await squareNumber(10);// no then no callback
const secondSqare = await squareNumber(firstSqare);
const thirdSqare = await squareNumber(secondSqare);
return thirdSqare; // return the final promise
}
someOtherFunctionAsync().then((data) =>
console.log(data)
).catch((err) =>
console.log(err)
);
Remember the promise chaining we had to do before? Now, async/await makes our code look like regular synchronous code!
The second await will not run until the first await either resolves or rejects, the third await will not run until the second await either resolves or rejects and return will not run until all previous awaits either resolve or reject.
If any of the promise rejects, for example if we pass in a string instead of the number 10 in our squareNumber function, the promise is going to reject with: reject("Number not provided");that we coded in squareNumber.
Now in someOtherFunctionAsync, away will automatically throw that error further for us, so no need to manually throw the error by typing throw new Error("error")
Converting our getCountryByCode function to async would look something along those lines:
const getCountryByCode = (code) => {
return fetch(`https://restcountries.com/v3.1/alpha/${code}`).then((response) => {
if (response.status === 200) {
return response.json(); // RETURNS ANOTHER PROMISE
} else {
throw new Error("Unable to fetch country");
}
});
}
const getCountryByCodeAsync = async (code) => {
const response = await fetch(`https://restcountries.com/v3.1/alpha/${code}`); // await
if (response.status === 200) {
return response.json(); // await here if you want to return something inside the response
} else {
throw new Error("Unable to fetch country");
}
}
I also converted the getCountriesByLanguage to async, now if I want to make a function that will chain the two calls together like we did above using the promise version, it would look something like this:
const getCountriesByLanguageUsingCountryCodeAsync = async (code) => {
const country = await getCountryByCodeAsync(code);
const countryLanguage = Object.values(country[0].languages)[0];
const allCountriesUsingLanguage = await getCountriesByLanguageAsync(countryLanguage);
return allCountriesUsingLanguage.map(i => i.name).map(i => i.official);
}
getCountriesByLanguageUsingCountryCodeAsync("FR").then((data) => {
console.log(data);
}).catch((err) => {
console.log(`Error: ${err}`);
})

So there you have it. This part may have been a bit lengthy, but there are numerous nuances to consider, making it an important subject so I wanted to cover the basics. In the future it would be interesting to go more in depth and explore things like the differences between JavaScript's Promises and C#'s Tasks, using side-by-side code examples in both languages.
You can find the full set of examples over at my github page.
Also if you liked the article, I'm constantly tweeting about this stuff and more. Feel free to follow me on Twitter and drop a comment to say hi!
In this third part of our three-part series, we will delve into the evolution of the JavaScript language in the context of asynchronous programming. If you wish to:
Let's begin with the following scenario: Suppose we have a method called "getCapitals" that utilizes an external API to fetch world capitals. How can we return the results from the "getCapitals" method without halting our entire system while waiting for the capitals to be fetched?
In a synchronous approach, we would simply wait for the capitals to be fetched, effectively blocking our program, and then use the "return" statement with the fetched data.
In an asynchronous approach, the first method we will explore is using the callback pattern.

const callbackFunction = function (result) {
console.log(result);
}
const fakeCapitals = getCapitalsFake(callbackFunction);
console.log("Continue doing some other work that does not depend on the capitals");
On the left (in “app.js” file)
I define a callback function that, when called, prints the capitals to the console.
then I just call the “requests.js“ getCapitals function passing in the callback function to be called with the fetched data.
const getCapitalsFake = (callbackFunction) => {
setTimeout(() => {
const data = "waiting 3 seconds for data to arrive...";
callbackFunction(data);
}, 3000)
}
On the right (in “requests.js” file) the GetCapitals function:
receives the callback function passed in as a parameter.
it makes a http request to the API in order to fetch the data
defines an inner event listener that listens when the data is ready
the method finishes its execution and gives back control to app.js to execute other code.
Only once the data arrives, the event listener triggers and from within the listener we call the callback function from “app.js” received as param, passing it the result data.
Above I excluded all the boilerplate code of making the http request and listening for the result for brevity. Here is the actual code:
const getCapitals = (callback) => {
const request = new XMLHttpRequest()
request.addEventListener('readystatechange', (e) => {
if (e.target.readyState === 4 && e.target.status === 200) {
const data = JSON.parse(e.target.responseText);
console.log(data)
callback(undefined, data.map(d => d.capital).flat());
} else if (e.target.readyState === 4) {
callback('An error has taken place', undefined);
}
});
request.open('GET', 'https://restcountries.com/v3.1/all?fields=capital');
request.send();
}
And here is the code that calls the getCapitals method. Please note I used an anonymous arrow function as parameter instead of declaring the callback separately:
getCapitals((error, capitals) => {
if (error) {
console.log(`Error: ${error}`)
} else {
console.log(capitals)
}
});
Promises in JS are like Tasks in C#. To create a new promise we use its constructor that expects two callback functions as parameters. One that should be called on success and one on failure:
const myPromise = new Promise((resolve, reject) => {
setTimeout(() => {
const currentSeconds = new Date().getSeconds();
if (currentSeconds % 2 === 0) {
resolve("I am the data from the API endpoint");
}
else {
reject("I am an error, the API endpoint was down");
}
}, 2000)
});
In order to get the result back from a promise we use “then”. then is a method on the Promise object and it requires two functions as parameters:
a function that will be called when the Promise will be resolved with the data
a function that will be called when the Promise will be rejected with the error
myPromise.then((data) => {
console.log(data);
}, (err) => {
console.log(err);
})
in order to allow the promise access some data we can wrap a function around it that returns the promise like so:
const getPromiseFunction = (seedNumber) => {
return new Promise((resolve, reject) => {
//code excluded for brevity
});
Or better, simplify the syntax further by removing the “{} and return” since “getPromiseFunction” is a function that receives a number as param and returns a promise.
const getPromiseFunction = (seedNumber) => new Promise((resolve, reject) => {
setTimeout(() => {
const currentSeconds = new Date().getSeconds() + seedNumber;
if (currentSeconds % 2 === 0) {
resolve("I am the data from the API endpoint");
}
else {
reject("I am an error, the API endpoint was down");
}
}, 2000)
});
const myPromise2 = getPromiseFunction(3)
.then((data) => {
console.log(data);
}, (err) => {
console.log(err);
})
Now that we know what a promise is, we can use fetch API (which returns a promise) for making requests, instead of the low level "XMLHttpRequest”.
In our requests.js I will add the following method:
const getCountryByCode = (code) => {
const url = `https://restcountries.com/v3.1/alpha/${code}`;
return fetch(url).then((response) => {
if (response.status === 200) {
return response.json(); // RETURNS ANOTHER PROMISE
} else {
throw new Error("Unable to fetch country");
}
});
}
And in our “app.js“ I can get the result by calling the method as such:
getCountryByCode("US").then((data) => {
console.log(data);
}).catch((err) => {
console.log(`Error: ${err}`);
})
Now let’s break down the code.
Fetch returns a promise, so instead of doing “const getCountryByCode = (code) => new Promise()“ I can do directly “const getCountryByCode = (code) => fetch()“.
Going further, you can see that I already called “then” once on fetch. So instead of the promise returned by fetch I’m actually returning the promise returned by “response.json()”. This returns a promise with the response data. If something goes wrong I throw the error to be caught down the line.

Further, on the calling side I am calling “then” again on the response data promise in order to get the actual data from the response.
If any error occurs on any of the two “then“ (the one on “fetch” and the one on “getCountryByCode“) the attached “catch” will catch and log the error.
This is called chaining and is one of the biggest advantages that promises offer. Let’s further explore it.
Going back to our first API call example where we used the callback pattern, imagine you have a scenario where you need to fetch a country code by its name, then from the result you use the country code to fetch it’s capital, and then you would use the capital to fetch it’s population. Using the callback pattern would result in a hard to read, hard to maintain and error prone multi-nested code that’s often referred to as “callback hell”. By returning a promise instead of nesting a callback function you achieve promise chaining and avoid this callback hell.
We will first look at an example of a square function returning a promise. The function squares a number and takes 1 second to execute (imagine it’s part of a different API and data has to be fetched). We will square the result three times:
const squareNumber = (num) => new Promise((resolve, reject) => {
setTimeout(()=>{
typeof num === "number" ? resolve(num * num) : reject("Number not provided");
}, 1000)
})
This approach is close to the callback hell that you would be forced to do with callback pattern:
squareNumber(10).then((data) => {
squareNumber(data).then((data) => {
squareNumber(data).then((data) => {
console.log(data);
}, (err) => {
console.log(err);
})
}, (err) => {
console.log(err);
})
}, (err) => {
console.log(err);
})
But with promises instead of resolving on the spot with “then” we can choose to simply call the function and let it return the promise:
squareNumber(10).then((data) => {
return squareNumber(data)
}).then((data) => {
return squareNumber(data)
}).then((data) => {
console.log(data);
}).catch((err) => {
console.log(err)
})

Returning a promise from another promise it's called chaining.
Now let’s use a real world example. I will use the getCountryByCode defined earlier and also add a new request getCountriesByLanguage:
const getCountriesByLanguage = (language) => fetch(`https://restcountries.com/v3.1/lang/${language}`).then((response) => {
if (response.status === 200) {
return response.json();
} else {
throw new Error("Unable to fetch countries");
}
})
Now I will chain the two calls together:
first get a country by code, then search into the object and get the country’s first language
then use the language to get all countries that use the language fetched earlier as their first language.
getCountryByCode("US").then((country) => {
const language = Object.values(country[0].languages)[0];
return getCountriesByLanguage(language);
}).then((countries) => {
console.log(countries.map(i => i.name).map(i => i.official));
}).catch((err) => {
console.log(`Error: ${err}`);
})
.Net devs rejoice! Yet another feature borrowed from C#, which makes my life a lot easier in working with JavaScript!
Microsoft first introduced async/await pattern in C# 5.0 back in 2011-2012, and was adopted by several programming languages. And rightfully so because this was one of the greatest contributions to asynchronous programming.
Let’s explore how async/await builds on promises (Tasks in C#) and makes our code a whole lot easier to work with.
Below is a regular function that returns a string:
const someFunction = () => {
return "some text";
}
console.log(someFunction()); // prints: some text
and this is what happens when I make the function async:
const someFunctionAsync = async () => {
return "some other text";
}
console.log(someFunctionAsync()); // prints: Promise { 'some other text' }
It will make the function return a promise instead of the string itself

We can get the string by resolving the promise like we always do:
someFunctionAsync().then((data) =>
console.log(data)
).catch((err) =>
console.log(err)
);
Now in order to demonstrate await, do you remember our squareNumber function that returned a promise? We will call that in our function again three times passing in the result and see how async/await compares to promise chaining:
const someOtherFunctionAsync = async () => {
const firstSqare = await squareNumber(10);// no then no callback
const secondSqare = await squareNumber(firstSqare);
const thirdSqare = await squareNumber(secondSqare);
return thirdSqare; // return the final promise
}
someOtherFunctionAsync().then((data) =>
console.log(data)
).catch((err) =>
console.log(err)
);
Remember the promise chaining we had to do before? Now, async/await makes our code look like regular synchronous code!
The second await will not run until the first await either resolves or rejects, the third await will not run until the second await either resolves or rejects and return will not run until all previous awaits either resolve or reject.
If any of the promise rejects, for example if we pass in a string instead of the number 10 in our squareNumber function, the promise is going to reject with: reject("Number not provided");that we coded in squareNumber.
Now in someOtherFunctionAsync, away will automatically throw that error further for us, so no need to manually throw the error by typing throw new Error("error")
Converting our getCountryByCode function to async would look something along those lines:
const getCountryByCode = (code) => {
return fetch(`https://restcountries.com/v3.1/alpha/${code}`).then((response) => {
if (response.status === 200) {
return response.json(); // RETURNS ANOTHER PROMISE
} else {
throw new Error("Unable to fetch country");
}
});
}
const getCountryByCodeAsync = async (code) => {
const response = await fetch(`https://restcountries.com/v3.1/alpha/${code}`); // await
if (response.status === 200) {
return response.json(); // await here if you want to return something inside the response
} else {
throw new Error("Unable to fetch country");
}
}
I also converted the getCountriesByLanguage to async, now if I want to make a function that will chain the two calls together like we did above using the promise version, it would look something like this:
const getCountriesByLanguageUsingCountryCodeAsync = async (code) => {
const country = await getCountryByCodeAsync(code);
const countryLanguage = Object.values(country[0].languages)[0];
const allCountriesUsingLanguage = await getCountriesByLanguageAsync(countryLanguage);
return allCountriesUsingLanguage.map(i => i.name).map(i => i.official);
}
getCountriesByLanguageUsingCountryCodeAsync("FR").then((data) => {
console.log(data);
}).catch((err) => {
console.log(`Error: ${err}`);
})

So there you have it. This part may have been a bit lengthy, but there are numerous nuances to consider, making it an important subject so I wanted to cover the basics. In the future it would be interesting to go more in depth and explore things like the differences between JavaScript's Promises and C#'s Tasks, using side-by-side code examples in both languages.
You can find the full set of examples over at my github page.
Also if you liked the article, I'm constantly tweeting about this stuff and more. Feel free to follow me on Twitter and drop a comment to say hi!
No activity yet