1. Promises
JavaScript is a synchronous programming language. However, callback functions enable us to transform it into an asynchronous programming language. Promises are to help to get out of “callback hell” while dealing with the asynchronous code and do much more.
Promise is always Async
const promise = new Promise((resolve, reject) => {
let sheLovesMe = true;
if (sheLovesMe) {
resolve("Let's Marry");
} else {
reject("Let's Breakup");
}
});
promise
.then((val) => { return val })
.then((val) => console.log(val))
.catch((val) => console.log(val))
.finally(() => console.log("All sorted now"));
// Output:
Let's Marry
All sorted now
2. Async Await
New syntax introduced in ES6 that helps to process the promise in a better way.
const promise = Promise.resolve("I am happy");
async function example(promise) {
try {
const response = await promise;
console.log("Try: " + response);
} catch (error) {
console.log("Catch: " + error);
} finally {
console.log("All set");
}
}
example(promise);
// Output
Try: I am happy
All set
----------
// const promise = Promise.reject("I am sad");
Catch: I am sad
All set
3. Synchronous v/s Asynchronous
Sync means line by line execution. Sync is a single-thread, so only one operation will run at a time.
Async means code execution in a non-blocking manner. Code which takes time will be executed later. Async is multi-thread, which means operations can run in parallel.
console.log("start")
console.log("middle")
console.log("end")
// Synchronous
start
middle
end
console.log("start")
setTimeout(() => console.log("middle"), 1000)
console.log("end")
// Asynchronous
start
end
middle (after 1s)
4. Callback
Due to Async nature we will see weird code outputs. So inorder to prevent that we use callbacks.
Passing function as a argument to another function is Callback.
function middleAction(name) {
setTimeout(() => {
return "Hello " + name
}, 1000)
}
console.log("start")
let message = middleAction("Arjunan", )
console.log(message)
console.log("end")
// start
// undefined
// end
-----
function middleAction(name, cb) {
setTimeout(() => {
cb("Hello " + name)
}, 1000)
}
console.log("start")
middleAction("Arjunan", (message) => {
console.log(message)
})
console.log("end")
// start
// end
// Hello Arjunan
5. Pyramid of Doom / Callback Hell
To fix Async code issues using callbacks in large code base result in a pyramid of callbacks. This is known as Pyramid of Doom / Callback Hell
function middleAction(name, cb) {
setTimeout(() => {
cb("Hello " + name);
}, 1000);
}
function whatIsTheAge(age, cb) {
setTimeout(() => {
cb("Age is " + age);
}, 500);
}
function whatIsThePlace(place, cb) {
setTimeout(() => {
cb("Place is " + place);
}, 100);
}
console.log("start");
middleAction("Arjunan", (message) => {
console.log(message);
});
whatIsTheAge(12, (message) => {
console.log(message);
});
whatIsThePlace("London", (message) => {
console.log(message);
});
console.log("end");
// start
// end
// Place is London
// Age is 12
// Hello Arjunan
middleAction("Arjunan", (message) => {
console.log(message);
whatIsTheAge(12, (message) => {
console.log(message);
whatIsThePlace("London", (message) => {
console.log(message);
whatIsTheJob("Dev", (message) => {
console.log(message);
whatIsTheDomain("Frontend", (message) => {
console.log(message);
});
});
});
});
});
// Hello Arjunan
// Age is 12
// Place is London
// Job is Dev
// Domain is Frontend
6. Callback Hell to Promises
Nice we have Promise Hell now :)
function middleAction(name) {
return new Promise((resolve, reject) => {
setTimeout(() => {
resolve("Hello " + name);
}, 2000);
});
}
function whatIsTheAge(age) {
return new Promise((resolve, reject) => {
setTimeout(() => {
resolve("Hello " + age);
}, 500);
});
}
function whatIsThePlace(place) {
return new Promise((resolve, reject) => {
setTimeout(() => {
resolve("Hello " + place);
}, 1000);
});
}
console.log("start");
middleAction("Arjunan").then((res) => {
console.log(res);
whatIsTheAge(12).then((res) => {
console.log(res);
whatIsThePlace("London").then((res) => console.log(res));
});
});
console.log("end");
Promise.resolve(console.log("Promise Resolved"));
// start
// end
// Promise Resolved
// Hello Arjunan
// Hello 12
// Hello London
7. Use Promise Chaining
console.log("start");
middleAction("Arjunan")
.then((res) => {
console.log(res);
return whatIsTheAge(12);
})
.then((res) => {
console.log(res);
return whatIsThePlace("London");
})
.then((res) => {
console.log(res);
})
.catch((err) => {
console.log(err);
});
console.log("end");
Promise.resolve(console.log("Promise Resolved"));
// start
// end
// Promise Resolved
// Hello Arjunan
// Hello 12
// Hello London
8. Promise.all
Takes a array of promises. It rejects if any one promise reject. It resolves only if all promises are resolved.
Promise.all keeps the order of array irrespective of execution time.
function whatIsTheName(name) {
return new Promise((resolve, reject) => {
setTimeout(() => {
resolve("Hello " + name);
}, 2000);
});
}
function whatIsTheAge(age) {
return new Promise((resolve, reject) => {
setTimeout(() => {
resolve("Hello " + age);
}, 500);
});
}
function whatIsThePlace(place) {
return new Promise((resolve, reject) => {
setTimeout(() => {
resolve("Hello " + place);
}, 1000);
});
}
Promise.all([
whatIsTheName("Arjunan"),
whatIsTheAge(12),
whatIsThePlace("London"),
])
.then((res) => console.log(res))
.catch((err) => console.log("Error: " + err));
// [ 'Hello Arjunan', 'Hello 12', 'Hello London' ]
-----
function whatIsTheName(name) {
return new Promise((resolve, reject) => {
setTimeout(() => {
reject("Hello " + name);
}, 2000);
});
}
// ERROR!
// Error: Hello Arjunan
9. Promise.race
It returns the first promise which gets resolved or rejected. Time is the preference, not fullfillment.
10. Promise.allSettled
It returns all promises in a array even it is resolved or rejected.
11. Promise.any
Similar to race but ignores rejected promise and returns the first resolved promise.
If all promises are rejected it returns, Error: AggregateError: All promises were rejected.
12. What is the Output?
JS engine find the Sync code inside the Promise so it will executed in order and at last it will execute Async code.
console.log("start");
let promise1 = new Promise((resolve, reject) => {
console.log(1);
resolve(2);
console.log(3);
});
promise1.then((res) => {
console.log(res);
});
console.log("end");
start
1
3
end
2
13. What is the Output?
console.log("start");
let promise1 = new Promise((resolve, reject) => {
console.log(1);
console.log(3);
});
promise1.then((res) => {
console.log("Result: " + res);
});
console.log("end");
start
1
3
end
14. What is the Output?
console.log("start");
const fn = () => {
new Promise((resolve, reject) => {
console.log(1);
resolve("Success");
});
};
fn().then((res) => {
console.log(res);
});
console.log("end");
// TypeError: Cannot read properties of undefined (reading 'then')
console.log("start");
const fn = () => {
return new Promise((resolve, reject) => {
console.log(1);
resolve("Success");
});
};
fn().then((res) => {
console.log(res);
});
console.log("end");
// start
// 1
// end
// Success
15. What is the Output?
function job() {
return new Promise((resolve, reject) => {
reject();
});
}
let promise = job();
promise
.then(() => {
console.log("Success 1");
})
.then(() => {
console.log("Success 2");
})
.then(() => {
console.log("Success 3");
})
.catch(() => {
console.log("Error 1");
})
.then(() => {
console.log("Success 4");
});
// Error 1
// Success 4
16. What is the Output?
function job(state) {
return new Promise((resolve, reject) => {
if (state) {
resolve("Success");
} else {
reject("Failed");
}
});
}
let promise = job(true);
promise
.then((data) => {
console.log(data);
return job(false);
})
.catch((err) => {
console.log(err);
return "Error Caught";
})
.then((data) => {
console.log(data);
return job(true);
})
.catch((err) => {
console.log(err);
return "Error Caught";
});
// Success
// Failed
// Error Caught
17. Throw v/s New Error
New Error will not go inside catch. it is basically just a return of data, which is a not a actual error.
throw "something" or throw new Error will definetly go inside catch. It is actually throwing a error.
function job(state) {
return new Promise((resolve, reject) => {
if (state) {
resolve("Success");
} else {
reject("Failed");
}
});
}
let promise = job(true);
promise
.then((data) => {
console.log(data);
return job(true);
})
.then((data) => {
if (data !== "Victory") {
throw "Defeat";
}
return job(true);
})
.then((data) => {
console.log(data);
})
.catch((err) => {
console.log(err);
return job(false);
})
.then((data) => {
console.log(data);
return job(true);
})
.catch((err) => {
console.log(err);
return "Error Caught";
})
.then((data) => {
console.log(data);
return new Error("test");
})
.then((data) => {
console.log("Success 1: " + data.message);
throw new Error("test");
})
.then((data) => {
console.log("Success 2: " + data.message);
})
.catch((data) => {
console.log("Error: " + data.message);
});
// Success
// Defeat
// Failed
// Error Caught
// Success 1: test
// Error: test
18. Promise Chaining I
const firstPromise = new Promise((resolve, reject) => {
resolve("first");
});
const secondPromise = new Promise((resolve, reject) => {
resolve("second");
});
secondPromise.then((res) => {
firstPromise.then((res) => {
console.log(res);
});
console.log(res);
});
// second
// first
19. Promise Chaining II
const firstPromise = new Promise((resolve, reject) => {
resolve("first");
});
const secondPromise = new Promise((resolve, reject) => {
resolve(firstPromise);
});
secondPromise
.then((res) => {
return res;
})
.then((res) => {
console.log(res);
});
// first
20. Rewrite in Async/Await instead of then/catch
loadJSON("https://fakeurl.com/no-such-user-exist.json")
.then((res) => console.log(res))
.catch((err) => console.log(err));
// Then & Catch
function loadJSON(url) {
return fetch(url).then((response) => {
if (response.status == 200) {
return response.json();
} else {
throw new Error("No JSON exist: " + response.status);
}
});
}
// Async & Await
async function loadJSON(url) {
const response = await fetch(url);
if (response.status == 200) {
const data = await response.json()
return data
}
throw new Error("No JSON exist: " + response.status);
}
21. Recursive Promises
function whatIsTheName(name) {
return new Promise((resolve, reject) => {
setTimeout(() => {
resolve("Hello " + name);
}, 2000);
});
}
function whatIsTheAge(age) {
return new Promise((resolve, reject) => {
setTimeout(() => {
resolve("Hello " + age);
}, 500);
});
}
function whatIsThePlace(place) {
return new Promise((resolve, reject) => {
setTimeout(() => {
resolve("Hello " + place);
}, 1000);
});
}
function PromiseRecursive(promises) {
if (promises.length === 0) return;
let currPromise = promises.shift();
currPromise.then((res) => console.log(res)).catch((err) => console.log(err));
PromiseRecursive(promises);
}
PromiseRecursive([
whatIsTheName("Arjunan"),
whatIsTheAge(12),
whatIsThePlace("London"),
]);
// Hello 12
// Hello London
// Hello Arjunan
22. Promises & setTimeout output
setTimeout(() => {
console.log('start')
}, 0);
Promise.resolve('start promise').then((res) => console.log(res))
new Promise((res, rej) => {
console.log('1')
setTimeout(() => { console.log('2') }, 0);
res('response')
return;
console.log('3');
}).then((res) => {
setTimeout(() => {
console.log('4')
}, 0);
console.log(res);
})
// ouput
// 1
// start promise
// response
// Promise {<fulfilled>: undefined}
// start
// 2
// 4