javascript promises

Please Do the Following 👇Before Picking a JavaScript Framework (Part 2)

This is a continuation of my last post if you missed the first series, please read it here.

We would go into a quick introduction to the following.

  • Promises
  • Classes
  • Functional Programming(Higher-Order Functions)

I will write a list of websites you can visit to learn more in details (References)

Promises

A Promise in JavaScript looks like a promise made in real life. As promises in real life are either kept or broken, JavaScript Promises get either resolved or rejected.

A Promise is an object representing the eventual completion or failure of an asynchronous operation.

What is an asynchronous operation?

Asynchronous operation is a process operates independently of other processes.

Essentially, a promise is a returned object to which you attach callbacks, instead of passing callbacks into a function.

Imagine a function, createUserAccount(), which asynchronously generates a creates a new user account on an insurance company website and has two callback functions, one called if the user account was created successfully, and the other called if an error occurs.

 

function successfulRegistration(username) {
  return `${username} has been successfully created`;
}

function failedRegistration(error_message) {
  return error_message;
}
createUserAccount(verifyUser, successCallback, failureCallback);

If createUserAccount() were rewritten to return a promise, it would look like the following below

createUserAccount(verifyUser).then(successCallback, failureCallback);

The constructor syntax for a promise object is

var promiseObject = new Promise(executor);

var  promiseObject = new Promise(function(resolve, reject) {
  if (/* everything turned out fine */) {
    resolve("Stuff worked!");
  }
  else {
    reject(Error("It broke"));
  }
});

The above promise constructor takes one argument, a callback with two parameters, resolve and reject. If an action was completed then call resolve, if not, otherwise call reject.

A Promise is in one of these states:

  • pending: initial state, neither fulfilled nor rejected.
  • fulfilled: meaning that the operation completed successfully.
  • rejected: meaning that the operation failed.

If the promise is successful, the data will load, if  unsuccessful, an error will occur:

const getUser = user_id => new Promise((resolves, rejects) => {
 const api = `https://fakeurl.com/${user_id}`
 const request = new XMLHttpRequest();
 request.open('GET', api);
 req.onload = () => {
  if (req.status == 200) {
   resolve(req.response);
  } else {
   reject(req.statusText);
  }
 };
 request.onerror = () => reject(request.statusText);
 request.send();
});

 

Classes

A class is a type of function, but instead of using the keyword function to initiate it, we use the keyword class, and the properties are assigned inside the constructor() method.

Class declarations

class User {
  constructor(name,age,email) {
    this.age = age;
    this.name = name;
    this.email = email;
  }
}

NOTE:

The constructor() method is a special method for creating and initializing an object created with a  class. There can only be one special method with the name “constructor” in a class.

A SyntaxError will be thrown if the class contains more than one occurrence of a constructor() method.

PROTOTYPE METHODS IN CLASSES
class User {
	constructor(name, age, email) {
		this.age = age;
		this.name = name;
		this.email = email;
	}
	returnAge() {
		return `My name is ${this.name} and I'm ${this.age } years old`;
	}
}

Now

  • Create a new instance of the class using the new keyword.
  • Then you can call the custom method on the class
    const user = new User("Mark", 24, "mark@gmail.com"); 
    console.log(user.returnAge()); //My name is Mark and I'm 24 years old
Static Methods

Static methods are defined on the class itself, and not on the prototype.

That means you cannot call a static method on the object (user), but on the class (User)

class User { 
constructor(name,age,email) { 
this.age = age;
this.name = name;
this.email = email;
}
returnAge() {
    return `My name is ${this.name} and I'm ${this.age } years old`;
  }
static salutations() {
  return "Hello,nice to meet you!";
 }
}
greeting = User.salutations();
console.log(greeting) // Hello,nice to meet you!

To  use the user object inside the static method, we need to  send it as a parameter:

class User { 
constructor(name,age,email) { 
this.age = age;
this.name = name;
this.email = email;
}
returnAge() {
    return `My name is ${this.name} and I'm ${this.age } years old`;
  }
static salutations(user_field) {
  return `Hello ${user_field.name} ,nice to meet you!`;
 }
}
const user = new User("Mark", 24, "mark@gmail.com"); 
console.log(User.salutations(user)) // Hello Mark ,nice to meet you!
Inheritance

To create a class inheritance, use the `extend` keyword.

If there is a constructor present in the subclass, it needs to first call super() before using this.

class User { 
constructor(name,age,email) { 
this.age = age;
this.name = name;
this.email = email;
}
returnAge() {
    return `My name is ${this.name} and I'm ${this.age } years old`;
  }
static salutations(user_field) {
  return `Hello ${user_field.name} ,nice to meet you!`;
 }
}

class VerifiedUser extends User {
  constructor(name, state) {
    super(name);
    this.state = state;
  }
  verifyUserLocation() {
    return `Hello ${this.name},you stay at ${this.state}!`;
  }
}

user = new VerifiedUser("Tom", "Georgia");
console.log(user.verifyUserLocation())   //Hello Tom,you stay at Georgia!

 

Functional Programming(Higher-Order Functions)

A function that accepts and/or returns another function is called a higher-order function.

Map(), Filter(), Reduce() are all higher-order functions (array methods) in JavaScript. Each one iterates over an array and perform a modification or computation and  returns a new array based on the result of the function.

Let me show you a funny illustration

map,filter,reduce image

Image credit

Map

The map() is a method used for creating a new array from an existing one by calling a function for every array element (transforming arrays).

Transforming every element in an array into a new one and collecting the results is called mapping.
Syntax

var new_array = arr.map(function callback(currentValue, index, array) {
    // Return value for new_array
})

Only the currentValue(value of the current element) is required, but other function parameters (index and array)are optional. The index represents the array index of the current element and array is the array object the current element belongs to.

Examples:

  • Let’s change an array of strings to UpperCase letters
  • Find the square root for an array of numbers.
const letters = ["georgia","london","usa","uae"];
const upper_case = letters.map(letter => letter.toUpperCase());
console.log(upper_case); // Array(4) [ "GEORGIA", "LONDON", "USA", "UAE" ]


const nums = [450,56,9,16,64];
const num_root = nums.map(Math.sqrt);
console.log(num_root); // Array(5) [ 21.213203435596427, 7.483314773547883, 3, 4, 8 ]
filter

The filter() method creates an array filled with all array elements that pass a test (provided as a function). The function should return true to keep the element, or false otherwise (like a boolean)

Syntax

var new_array = arr.filter(function callback(currentValue, index, array) { // Return value for new_array })

The syntax of the filter() is similar to the map() method,only the currentValue is required, but other function parameters (index and array)are optional.

Examples:

  • Let’s return only arrays of numbers greater than 1000
  • Let’s return only arrays of strings that start with Y
const letters = ["You are good!","Hello", "arriving","Yellow Sun"];
const startWithY = letters.filter(letter => letter.startsWith("Y"));
console.log(startWithY);  // [ "You are good!", "Yellow Sun" ]


const numbers = [40000,678000,678,340,3456];
const num = numbers.filter(item => item > 1000);
console.log(num); // [ 40000, 678000, 3456 ]


Reduce

The reduce method reduces the array to a single value.

Syntax

array.reduce(function(initialValue, currentValue, currentIndex, array))

The initialValue (the total previously returned value of the function)  and currentValue (the value of the current element) are both required, but other function parameters (index and array)are optional.

Example:

  • Let’s imagine a bank log transaction that shows all the credit transaction a customer carried out, let’s return the final customer balance after each transaction.

 

const transactions = [570, 5679, 567, 234,6700];

transactions.reduce(function (totalBalance, nextTransaction) {
    console.log(`Your current bank balance: ${totalBalance}`)

    // update totalBalance by adding the next credit transaction
    totalBalance += nextTransaction

})

//Output
Your current bank balance: 570 
Your current bank balance: 6249 
Your current bank balance: 6816 
Your current bank balance: 7050

 

If you made it to the end of this series, a big congratulations 🎉🎉 and thank you for reading.

I love to hear your feedback and don’t forget to subscribe, so you stay updated when I publish a new post.

References

 

 

2 Comments

Leave a Reply

Your email address will not be published. Required fields are marked *