Couple of rules to keep when Designing API Methods in JavaScript

Couple of rules to keep when Designing API Methods in JavaScript

This article will go over a couple of rules to keep in mind when designing methods for an API in JavaScript

Designing API methods in JavaScript is a very useful skill to learn and allows you to look at programming in a different perspective. A perspective whereas instead of building a project for your users, you're building a project for developers to use. And if you haven't built a library or an SDK before, this article may help you gain an understanding of where and how to start beginning with method design.

JavaScript is a loosely typed language which we as developers can take advantage of to create robust, multi-use APIs.

This article will go over a couple of rules to keep in mind when designing methods for an API in JavaScript.

1. Named Parameters

The first one we are going to talk about is named parameters. Back in the old days before ES6 was introduced, the only way to declare functions were function declarations using the function syntax. To determine where to go with execution flows, you would take a function arity (the number of arguments the function expects), convert it to an array and apply the rest of the logic depending on how the arguments look like.

In this example, the animal, options, and callback are the parameters to the function and the arity will be three. The function is designed to create a new account, and each account will have some default settings if it wasn't provided by the caller:

function createAccount(
  username = '',
  password = '',
  nickname = '',
  email = '',
  gender = 'Male',
  bio = '',
  subscription = 'Basic',
  callback,
) {
  if (!username || !password || !email) {
    throw new Error(
      'You are missing one or all of the following fields: "username", "password", "email"',
    )
  }
  return api
    .createAccount({
      username,
      password,
      nickname,
      email,
      gender,
      bio,
      subscription,
    })
    .then((result) => {
      if (callback) callback(null, result)
    })
    .catch((error) => {
      console.error(error)
      if (callback) callback(error)
    })
}

createAccount(
  'lucas',
  'applebee123x123',
  '',
  '[email protected]',
  '',
  'My bio',
  'Basic',
  function cb(err, data) {
    if (err) {
      console.error(err)
    }
    // do something with data
  },
)

The problem with this is that the caller has to know the exact order of arguments to pass in as the parameters to the function in order to function properly even if one or more parameters weren't required. It can be difficult to memorize the requirements in order while it can be very easy to mess up the order if you aren't careful. In addition, it doesn't really make much sense to make a parameter required if it isn't required to make the function do its work properly.

It will also be difficult to maintain in the future because when you or your boss needs to get rid of username and make it email as the new username instead, you would have to change the logic around.

A better practice is to simply use an object:

function createAccount({
  username = '',
  password = '',
  nickname = '',
  email = '',
  gender = 'Male',
  bio = '',
  subscription = 'Basic',
  callback,
}) {
  if (!username || !password || !email) {
    throw new Error(
      'You are missing one or all of the following fields: "username", "password", "email"',
    )
  }
  return api
    .createAccount({
      username,
      password,
      nickname,
      email,
      gender,
      bio,
      subscription,
    })
    .then((result) => {
      if (callback) callback(null, result)
    })
    .catch((error) => {
      console.error(error)
      if (callback) callback(error)
    })
}

We benefit from readability as well as more control over maintainability as you only need to remove the username from the code:

function createAccount({
  password = '',
  nickname = '',
  email = '',
  gender = 'Male',
  bio = '',
  subscription = 'Basic',
  callback,
}) {
  if (!password || !email) {
    throw new Error(
      'You are missing one or all of the following fields: "email", "password"',
    )
  }
  return api
    .createAccount({
      password,
      nickname,
      email,
      gender,
      bio,
      subscription,
    })
    .then((result) => {
      if (callback) callback(null, result)
    })
    .catch((error) => {
      console.error(error)
      if (callback) callback(error)
    })
}

Making the call also becomes more terse and readable:

createAccount({
  password: 'applebee123x123',
  email: '[email protected]',
  bio: 'My bio',
  callback: function cb(err, data) {
    if (err) {
      console.error(err)
    }
    // do something with data
  },
})
2. Method Chaining / Fluent API

My favorite way of writing APIs is using the fluent API by method chaining.

Method chaining is simply the process of chaining multiple calls one after the other. The general idea is to achieve a readable and fluent code, thus making it quicker to understand. These methods are commonly verbs (like rotate)

For example:

getPhoto('../nemo_the_fish.jpg')
  .applyFilter('grayscale', '100%')
  .rotate(100)
  .scale(1.5)

This translates to: "retrieve the image nemo_the_fish.jpg and apply the grayscale filter with a value of 100%, rotate the image by 100 degrees and increase the scale by 1.5 times more."

A good thing about this practice is that it's very quick to get started with writing your own fluent API interface. You would simply return the reference to the context inside your method calls so that it can be chained:

const createWarrior = function createWarrior(name) {
  let hp = 100
  let battleCryInterval = 0

  return {
    bash: function(target) {
      target -= 10
      return this
    },
    // Increase the wrarior's health by 60, decrementing it by 1 every second for 60 seconds
    battleCry: function battleCry() {
      hp += 60
      battleCryInterval = setInterval(() => {
        hp -= 1
      }, 1000)
      setTimeout(() => {
        if (battleCryInterval) {
          clearInterval(battleCryInterval)
        }
      }, 60000)
      return this
    },
    getHp: function getHp() {
      return hp
    },
  }
}

const warrior = createWarrior('chris')
const otherWarrior = createWarrior('bob')

warrior
  .battleCry()
  .bash(otherWarrior)
  .bash(otherWarrior)
  .bash(otherWarrior)
  .bash(otherWarrior)
  .bash(otherWarrior)

const otherWarriorsHp = otherWarrior.getHp()

console.log(otherWarriorsHp) // result: 100

One of the greatest examples of a fluent API is jQuery, and thanks to the library's fluency it arguably makes it one of the easiest JavaScript libraries to both learn and use:

$(window).resize(function() {
  $('#logbox').append('<div>The window resized</div>')
})

However, the method chaining fluent API comes with a few drawbacks.

The biggest drawback is that it can be difficult to set a breakpoint in the middle of a chain, making errors difficult to debug. In addition, it encourages too much procedural code. There are ways to get around the debugging issue though by inserting loggers at any step in the chain and using them to call subsequent methods with it.

Another drawback is that you can get caught up in the act of writing long sentences with tight dot notation access. This can get in the way of keeping things simple, so remember to keep things simple.

3. Function Polymorphism

You might have heard of the term polymorphism in other languages, generally where something behaves differently based on the context.

The same concept applies in function polymorphism in JavaScript. These are functions that behave accordingly to the arguments passed in (which is our context).

APIs often gather arguments to an array or array-like structure in order to have more control over them. Having them into an array structure allows them to do things like pass them into other functions in the same scope and vice versa.

Before arrow functions were introduced, the common practice to gather arguments inside polymorphic functions was using the array-like arguments object. Sometimes you might be in situations where you need to do more things with the arguments after you assigned them to an array. Even though arguments is an array-like object, it doesn't really function like a real array because it is missing essential array functions--and this is very limiting.

The way developers get around that is to make a separate, shallow copy by using Array.prototype.slice.call(). This is called method delegation. In order words, you delegate the slice() call to the Array.prototype object.

An example of this would look like this:

const args = Array.prototype.slice.call(arguments, 0)

This will copy the items starting at index 0 and return everything onwards.

Arguments doesn't have real methods like .push or .shift, so we convert it to an array with Array.prototype.slice so that we can get access to all of the array methods.

In ES6, we can easily convert it to an array by using the spread operator as shown below:

const someFunction = function(...args) {
  console.log(args)
  console.log(args.shift())
}

someFunction(1, 'hello', 'bob')
// result:
// [1, "hello", "bob"]
// 1

When you have your arguments into an array or array-like structure, you can determine where to go with the execution logic based on how the arguments look like. This makes it very flexible to be used for multiple purposes without writing too much code.

Without spreading:

const applyFilter = function(filter, value, options) => {
  const args = [].slice.call(arguments, 0)
  console.log(args.length) // result: 2
}

applyFilter('grayscale', '100%')

With spreading:

const applyFilter = (...args) => {
  console.log(args.length) // result: 1
}

applyFilter('grayscale', '100%')

With this in mind, we can now determine how to handle the execution from these arguments:

const applyFilterToImage = (image) => {
  return function applyFilter(...args) => {
  // we can also grab args with [].prototype.slice.call(arguments, 0)

    let options
    let filters = {}
    let callback

    const arg1 = args[0]
    // The caller wants to apply multiple filters
    if (args.length === 1) {
      if (arg1 && typeof arg1 === 'object') {
        filters = { ...arg1 }
        // Find out of the caller wants the new image with applied filters back by checking if a callback was passed in
        const arg2 = args[1]
        if (arg2 && typeof arg2 === 'function') {
          callback = arg2
        }
      } else {
        throw new Error(
          'You must supply an object if you are only providing the first argument',
        )
      }
    } else {
      if (args.length > 2) {
        // The caller passed in options as the third argument
        if (typeof args[3] === 'object') {
          options = args[3]
        }
          // The caller provided a callback function and wants the image with applied filters passed back
        else if (typeof args[3] === 'function') {
          callback = args[3]
        }
      }
      // The caller wants to apply one filter
      if (typeof arg1 === 'string') {
        const filter = arg1
        const value = args[1]
        filters[filter] = value // or filters = { [filter]: value }
      } else {
        if (callback) {
          callback(new Error('Filter is not a string'))
        }
      }
    }
      const newImg = api.filterImage(filters, options)
      if (callback) {
        return callback(null, newImg)
      }
  }
}

const img = '../bob_the_builder.jpg'
const applyFilter = applyFilterToImage(img)
const callback = (newImg) => {
  console.log(newImg)
}

applyFilter({
  grayscale: '100%',
  rotate: 100,
  scale: 1.5,
}, callback)

The simple function allows the developer to use it in multiple ways:

  1. Apply a single filter by providing a string and a value as the first and second argument.
  2. Or apply multiple filters by providing an object of key/value pairs as the first argument.
  3. Or apply a single filter by providing an object of one filter key/value as the first argument.
  4. Optionally receive the newly filtered image back through a callback as the second or third argument (position depends on what they passed in for the filters.)
Conclusion

That concludes the end of this article. Look out for more posts from me in the future!

Thank you for reading !

Angular 9 Tutorial: Learn to Build a CRUD Angular App Quickly

What's new in Bootstrap 5 and when Bootstrap 5 release date?

What’s new in HTML6

How to Build Progressive Web Apps (PWA) using Angular 9

What is new features in Javascript ES2020 ECMAScript 2020

Understand and Use JavaScript's .forEach() vs. jQuery's .each()

Understand and Use JavaScript's .forEach() vs. jQuery's .each()

There are two functions to deal with an array on the client-side – JavaScript's .forEach() and jQuery's .each(). Here, I will teach you how to use both of these methods with some sample code.

Your knowledge of JavaScript and jQuery is incomplete if you don't know how to loop with .forEach() and .each() methods. This tutorial helps you to quickly master JavaScript .forEach() & jQuery .each() in 2 minute time.

There are two methods to deal with an array on client-side – JavaScript .forEach() and jQuery .each(). Here, I will teach you how to use both of these methods in different scenarios.

Defination of these 2 methods

a. JavaScript .forEach() Method

The .forEach() method of JavaScript executes a given function once for each element of the array.

For example -

var arr = ['a', 'b', 'c'];    
arr.forEach(function(element) {  
    console.log(element);  
});  

The above JavaScript code will print – ‘a’, ‘b’, & ‘c’ in the console window.

b. jQuery .each() Method

jQuery has it’s own method called jQuery Each method and it is used to loop over arrays, array of object and matched elements of the DOM. See the below code:

var arr = ['a', 'b', 'c'];  
$.each(arr , function (index, value){  
  console.log(arr);   
});  

The above jQuery code will print – ‘a’, ‘b’, & ‘c’ in the console window.

Looping through DOM elements

a. JavaScript .forEach() Method

Suppose you want to extract all the anchor tags from the web page, and then loop through each of them. In that case first you have to get all the anchors using document.getElementsByTagName("a") and then convert it into an array. This is because JavaScript .forEach() method loops only through an array.

See the below code:

var links = document.getElementsByTagName("a");    
var Arr = Array.from(links);    
Arr.forEach(someFunction);    
    
function someFunction(currentValue) {    
    console.log(currentValue);    
}    

I used Array.from() method to convert to an array.

b. jQuery .each() Method

In case of .each() method you simply loop through all the anchor tags, like shown in the below code, as jQuery Each method can loop through arrays, array of objects and matched element of the DOM. So you don’t have to do the conversion to an array like JavaScript .forEach() method.

See the below code:

$("a").each(function (index, value) {   
  console.log($(this).attr("href"));   
});  

Clearly you can see in this case the lines of codes are very less than compared to .forEach() method of JavaScript.

Which one you should choose?

Case 1: DOM Manipulations

When working with DOM elements the jQuery Each method has a great advantage because it removes a lot of code lines. So prefer this method during DOM manipulations.

Case 2: Website is using jQuery from before

If your website is already using jQuery then you should use jQuery Each method because this will bring code consistency in your project.

In all other cases use JavaScript .forEach() method.

Conclusion

Both of these above methods are very good and they make the codes easy to understand. I would recommend every web developer to know both of these methods.

Thank you for reading.

Calling Rest API from JavaScript / jQuery

Calling Rest API from JavaScript / jQuery

How to call rest APIs in javascript/jquery. In this tutorial, you will learn how to call rest APIs in javascript/jquery on your web applications or web pages.

How to call rest APIs in javascript/jquery. In this tutorial, you will learn how to call rest APIs in javascript/jquery on your web applications or web pages.

If you are looking for how to consume restful web services in javascript, call rest service from HTML page, jquery rest API post, ajax API, call example, jquery API call, calling web API from jquery ajax, javascript call rest API JSON. This tutorial solves your all queries related to calling APIs (web services).

In this web services (Apis) tutorial, we will call Google’s free news web service (API). This will make it easier for you to learn how to call web service and API in JavaScript and Jquery using Ajax.

You might not know that Google provides free (web services) APIs for news. You can get the Google News API key by clicking on the link given below. https://newsapi.org/docs/get-started

Calling Google News RESTful Web Service with JavaScript / jQuery

This guide walks you through writing a simple javascript/jquery to calling rest web service.

Google News Apis key:

e03753c9126b408d870a44318813ac3d

This the google news web services (Apis)

https://newsapi.org/v2/top-headlines?country=us&apiKey=e03753c9126b408d870a44318813ac3d

When we call Google News API and web service with the help of javascript and jquery then we will get the JSON response given below.

[
{
"status": "ok",
"totalResults": 38,
"articles": [
    {
    "source": {
    "id": null,
    "name": "Youtube.com"
    },
    "author": null,
    "title": "Coronavirus: Death toll rises to 81 as China extends holiday  BBC News  BBC News",
    "description": "The number of people killed in China by the new coronavirus has risen to 81, with almost 3,000 confirmed ill. The national new year holiday has been extended...",
    "url": "https://www.youtube.com/watch?v=S2VoEvDEuxw",
    "urlToImage": "https://i.ytimg.com/vi/S2VoEvDEuxw/maxresdefault.jpg",
    "publishedAt": "20200127T10:35:49Z",
    "content": "The number of people killed in China by the new coronavirus has risen to 81, with almost 3,000 confirmed ill.
    The national new year holiday has been extended by three days to Sunday, in an attempt to contain the spread.
    On Monday, Chinese Premier Li Keqiang… [+268 chars]"
    },
 
    {
    "source": {
    "id": "thewashingtonpost",
    "name": "The Washington Post"
    },
    "author": "Gerry Shih, Simon Denyer",
    "title": "Worries grow that quarantine in China not enough to stem increasingly virulent coronavirus  The Washington Post",
    "description": "Even as the quarantine was being laid down, some 5 million people left Wuhan, the virus epicenter.",
    "url": "https://www.washingtonpost.com/world/coronaviruschinalatestupdates/2020/01/27/3634db9a40a711eaaa6a083d01b3ed18_story.html",
    "urlToImage": "https://www.washingtonpost.com/resizer/AaxiGLihZ1dJXlirb6FyJqaARSY=/1440x0/smart/arcanglerfishwashpostprodwashpost.s3.amazonaws.com/public/4O4ONFSA4YI6VKTKBA6QDM7NDA.jpg",
    "publishedAt": "20200127T10:21:00Z",
    "content": "Chinas health minister said the coronavirus is increasing in virulence and now could be contagious even before people exhibit symptoms making perfectly healthyseeming people possible carriers.
     A scientific assessment of the disease spread assuming an optim… [+10160 chars]"
    }
   ]
  }
]

Create a js File

First, you will create the js file and in this file call the web service (apis) :
public/my-news.js

$(document).ready(function() {
    $.ajax({
        url: "https://newsapi.org/v2/top-headlines?country=us&amp;apiKey=e03753c9126b408d870a44318813ac3d"
    }).then(function(data) {
        
        for (i = 0; i < data.articles.length; i++) {
          $('#news').append("<ul><li>"+data.articles[i].title+"</li></ul>");
        }
        
    });
});

This controller module is represented as a simple JavaScript function. It uses jQuery’s $.ajax() method to consume the REST service at https://newsapi.org/v2/top-headlines?country=us&apiKey=e03753c9126b408d870a44318813ac3d. If successful, it will assign the JSON received to data, effectively making it a Greeting model object. The id and content are then appended to the news id and DOM elements respectively.

Note the use of the jQuery promise .then(). This directs jQuery to execute the anonymous function when the $.ajax() method completes, passing the data result from the completed AJAX request.

Create the Web Page

Now that you have a js, you will create the HTML page that will load the google news into the user’s web browser:

public/index.html

<!DOCTYPE html>
<html>
    <head>
        <title>Google News Apis</title>
        <script src="https://code.jquery.com/jquery-3.4.1.js"></script>  
        <script src="my-news.js"></script>
    </head>
 
    <body>
        <div id="news"> </div>
    </body>
</html>

We need to add two jQuery /JavaScript libraries inside the head tag on html web page. The former gives jQuery. He: We have created another in which we will call Web Services / Interconnect

<script src="https://code.jquery.com/jquery-3.4.1.js"></script>  
<script src="my-news.js"></script>

We have created a div in an html web page. When calling Google’s free news API / web service, the format that will get the response, we will read in this div. Of the jquery append method ():

Call the API

Open your browser and simply hit the following url into your browser:

file:///C:/Users/Desktop/public/index.html

jQuery vs Vanilla JavaScript - Beau teaches JavaScript

jQuery vs Vanilla JavaScript - Beau teaches JavaScript

When should you use jQuery instead of vanilla JavaScript? Is jQuery still relevant? What is jQuery good for? jQuery vs vanilla JavaScript - Beau teaches JavaScript

When should you use jQuery instead of vanilla JavaScript? Is jQuery still relevant? What is jQuery good for? Find out in this video!