This blog mainly focuses on the creation of promises, rather than the explanation of promises, but here is a quick intro.
What is a promise?
Definitions from web-dev sites :MDN Docs: The Promise object represents an eventual completion(or failure) of an asynchronous operation and its resulting value..
W3Schools says: A Promise is a JavaScript object that links producing code and consuming code. they also describe - producing code and consuming code
Javascript Info says: A promise is a special JavaScript object that links the “producing code” and the “consuming code” together. they also describe - producing code and consuming code
And in my simple words
It is a way of delaying the synchronous operation until some async operations have been completed. without blocking the js execution thread.. you have different operations on success and failure of async task(.then for success and .catch for failure).
example see the syntax of promise -
first, you create a promise object
var promise = new Promise(function(resolve, reject) { //some task })..then you consume a promise by using syntax promise
promise
.then(()=>{})
.catch(()=>{})
You can have a chain of operations(multiple .then operations) on success but only 1 failure(for each .then)
- Creation of Promises - in 3 easy steps
step 2a)
Objective: Writing the basic things required..
Requirement: I need the async task that will happen, which will help me by getting the results so that i test my code..
example of written code)
function asyncWork(resolve, reject){
$.ajax({
url: "some image url",
type: 'GET',
success: function (resp) {
// if request is successfull
//calling the resolve function
if(resolve){
resolve(resp);
}
},
error: function (err) {
// if request is not successfull for any reason
//calling the reject function
if(reject){
reject();
}
}
});
}
NOTE: resolve and reject are the callback functions
NOTE: here I am using the ajax request for demo purposes (as i am familiar with ajax), you can use any other forms of requests also.
Some questions..
Point said above
resolve and reject are callback functions
- those call back functions which you will give in .then(()=>{}) and .catch(()=>{}) question 1) now how do the functions passed in .then and .catch reach to that async operations?
Answer 1) they are being passed internally by the promises itself to the .then and .catch..
question 2) how?
Answer 2) we usually pass the async task function itself to promise then promise takes the reference of that particular function.. promise takes the function(with the async task in its input), see the promise syntax above
step 2b)
Objective: writing the promise (polyfills) syntax which works just like promise..
function PromisePollyFills(executor){
let onResolve, onReject;
let fulfilled = false, called = false, value;
function resolveFun(val){
fulfilled = true;
value = val;
if(typeof onResolve === 'function')
{
onResolve(val);
called = true;
}
}
function rejectFun(val){
fulfilled = false;
value = val;
if(typeof onReject === 'function')
{
onReject(val);
called = true;
}
}
this.then = function(callback){
onResolve = callback;
if (fulfilled && !called) {
called = true;
onResolve(value);
}
return this;
}
this.catch = function(callback){
onReject = callback;
if(!fulfilled && !called){
called = true;
onReject(value);
}
return this;
}
executor(resolveFun, rejectFun);
}
Points to understand :
what promise is doing is whatever function you pass in the .then and .catch, it is taking that function and passing it to the executor function(along with some flags(to keep the track of promise) in resolveFun).
you see this executor function getting called.. executor function is a function that you pass in the promise(it is some async function like fetch, etc) executor is just a name, you can change it to Ash Ketchum(from pokemon) for example
we return a "this" object from inside of the ".then" and ".catch" functions, we do this because we want to return the whole promise and also so that we can chain the promises
step 2c)
Objective: Testing the PromisePollyFills's work..
example code)
function PromisePollyFills(executor){
let onResolve, onReject;
let fulfilled = false, called = false, value;
function resolveFun(val){
fulfilled = true;
value = val;
if(typeof onResolve === 'function')
{
onResolve(val);
called = true;
}
}
function rejectFun(val){
fulfilled = false;
value = val;
if(typeof onReject === 'function')
{
onReject(val);
called = true;
}
}
this.then = function(callback){
onResolve = callback;
if (fulfilled && !called) {
called = true;
onResolve(value);
}
return this;
}
this.catch = function(callback){
onReject = callback;
if(!fulfilled && !called){
called = true;
onReject(value);
}
return this;
}
executor(resolveFun, rejectFun);
}
//Resolve Case
function asyncWork(resolve, reject){
resolve("200");
//Here i am calling resolve directly but you can call it from inside of the async(inside ajax success case) operation
// $.ajax({
// url: "https://picsum.photos/200/300",
// type: 'GET',
// success: function (resp) {
// // if request is successfull
// //calling the resolve function
// if(resolve){
// resolve(resp);
// }
// },
// error: function (err) {
// // if request is not successfull for any reason
// //calling the reject function
// if(reject){
// reject(err);
// }
// }
// });
}
//reject case(callign the same function with just reject)
function asyncWork(resolve, reject){
reject("100");
//Here i am calling reject directly but you can call it from inside of the async operation(inside ajax error case)
// $.ajax({
// url: "https://picsum.photos/200/300",
// type: 'GET',
// success: function (resp) {
// // if request is successfull
// //calling the resolve function
// if(resolve){
// resolve(resp);
// }
// },
// error: function (err) {
// // if request is not successfull for any reason
// //calling the reject function
// if(reject){
// reject(err);
// }
// }
// });
}
//consume or use the promise as normal
var promise = new PromisePollyFills(asyncWork);
promise.then(function(result){
// success
console.log("inside Then : ", result);
}).catch(function(err){
//error
console.error("inside Catch : ", err);
});
NOTE: call the resolve, reject function after some async function like in step-2a..
FINAL RESULTS :
include the above code in your js file and create the promise
var promise = new PromisePollyFills(asyncWork);consuming the promise
var promise = new PromisePollyFills(asyncWork); promise.then(function(result){ //success will output 200 console.log("inside Then : ", result); }).catch(function(err){ //error will output 100 console.error("inside Catch : ", err); });
NOTE : asyncwork is just a normal asynchronous function that i have created as a dummy, you might want to pass your own async function..
That's all folks.. Hope this was helpful, Wish you all very well.. Happy new year to all.. Hope it helps you all create your promises, and fulfill them..