APIs: Arrays, Objects, and Seamless Data Handling

APIs: Arrays, Objects, and Seamless Data Handling

Let’s go step by step to understand arrays, and objects, and how to master them.

What Are Arrays?

An array is like a box with multiple compartments to store related items in order. For example:

const fruits = ["apple", "banana", "cherry"];

Here:

  • The array is called fruits.

  • It has three items: "apple", "banana", and "cherry".

  • Each item has a position (or index), starting from 0.

To get an item:

console.log(fruits[0]); // Output: "apple"
console.log(fruits[2]); // Output: "cherry"

Array Methods

Arrays have many tools (called methods) to help us work with them. Let’s go over some important ones:

1. forEach

Imagine you want to go through every item in the array and do something with it. forEach is like a loop that visits each item.

const fruits = ["apple", "banana", "cherry"];
fruits.forEach((fruit) => {
  console.log(fruit);
});
// Output:
// apple
// banana
// cherry

Here:

  • The fruit variable represents each item in the array as we loop through it.

2. map

Use map when you want to create a new array by transforming the items in the original array.

const numbers = [1, 2, 3];
const doubled = numbers.map((num) => num * 2);
console.log(doubled); // Output: [2, 4, 6]
  • Here, map takes each num, multiplies it by 2, and stores the result in the new array doubled.

3. filter

filter helps you keep only the items that meet a certain condition.

const numbers = [1, 2, 3, 4, 5];
const evenNumbers = numbers.filter((num) => num % 2 === 0);
console.log(evenNumbers); // Output: [2, 4]
  • .filter() creates a new array. It does not modify the original array; instead, it returns a new array that contains only the elements that satisfy the condition in the callback function.

  • It keeps only the numbers that are divisible by 2.


4. find

find stops as soon as it finds the first item that matches a condition.

const numbers = [1, 2, 3, 4, 5];
const firstEven = numbers.find((num) => num % 2 === 0);
console.log(firstEven); // Output: 2

5. slice

slice is used to extract a portion of an array without changing the original array.

const fruits = ["apple", "banana", "cherry", "date"];
const someFruits = fruits.slice(1, 3);
console.log(someFruits); // Output: ["banana", "cherry"]
console.log(fruits); // Original array remains unchanged

6. splice

splice is used to add/remove items from an array. Unlike slice, it modifies the original array.

const fruits = ["apple", "banana", "cherry"];
fruits.splice(1, 1, "orange");
console.log(fruits); // Output: ["apple", "orange", "cherry"]

Here:

  • 1, 1 means start at index 1 and remove 1 item.

  • "orange" replaces the removed item.


7. sort

sort is used to arrange items in order. By default, it sorts alphabetically for strings and in strange ways for numbers unless you guide it.

// Example 1: Sorting strings alphabetically
const fruits = ["banana", "apple", "cherry"];
fruits.sort(); // By default, .sort() arranges strings in alphabetical order
console.log(fruits); // Output: ["apple", "banana", "cherry"]

// Example 2: Sorting numbers from smallest to largest
const numbersAscending = [10, 5, 20];
numbersAscending.sort((a, b) => a - b); 
// Explanation:
// - The callback function takes two numbers, a and b.
// - `a - b` ensures numbers are arranged in ascending order (small to big).
console.log(numbersAscending); // Output: [5, 10, 20]

// Example 3: Sorting numbers from largest to smallest
const numbersDescending = [10, 5, 20];
numbersDescending.sort((a, b) => b - a); 
// Explanation:
// - The callback function takes two numbers, a and b.
// - `b - a` ensures numbers are arranged in descending order (big to small).
console.log(numbersDescending); // Output: [20, 10, 5]
  • Default Behavior:

    • If no callback function is provided, .sort() converts array elements into strings and compares them alphabetically.

    • This may lead to unexpected results when sorting numbers:

        const numbers = [10, 5, 20];
        numbers.sort(); 
        console.log(numbers); // Output: [10, 20, 5] (incorrect order for numbers)
      
  • Custom Sorting:

    • You can define a custom sorting logic by providing a callback function, as shown in the examples for numbers.

Sorting Numbers: Logic in Callback

  • (a, b) => a - b: Sorts numbers in ascending order (small to big).

  • (a, b) => b - a: Sorts numbers in descending order (big to small).


8. push & pop

  • push: Add an item to the end.

  • pop: Remove the last item.

const fruits = ["apple", "banana"];
fruits.push("cherry");
console.log(fruits); // Output: ["apple", "banana", "cherry"]

fruits.pop();
console.log(fruits); // Output: ["apple", "banana"]

9. shift & unshift

  • shift: Remove the first item.

  • unshift: Add an item to the beginning.

const fruits = ["apple", "banana"];
fruits.unshift("cherry");
console.log(fruits); // Output: ["cherry", "apple", "banana"]

fruits.shift();
console.log(fruits); // Output: ["apple", "banana"]

What Are Objects?

An object is like a box where each item has a label. For example:

const person = {
  name: "John",
  age: 25,
  isStudent: true
};

Here:

  • name, age, and isStudent are keys (labels).

  • "John", 25, and true are values.

To get a value:

console.log(person.name); // Output: "John"
console.log(person["age"]); // Output: 25

Object Methods

1. Object.keys()

Gets all the keys (labels).

console.log(Object.keys(person)); // Output: ["name", "age", "isStudent"]

2. Object.values()

Gets all the values.

console.log(Object.values(person)); // Output: ["John", 25, true]

3. Object.entries()

Gets everything as pairs (key and value).

console.log(Object.entries(person));
// Output: [["name", "John"], ["age", 25], ["isStudent", true]]

Destructuring

Destructuring is a shortcut to extract values from arrays or objects.

For Arrays:

const fruits = ["apple", "banana", "cherry"];
const [first, second] = fruits;
console.log(first); // Output: "apple"
console.log(second); // Output: "banana"

For Objects:

const person = {
  name: "John",
  age: 25,
  isStudent: true
};

const { name, age } = person;
console.log(name); // Output: "John"
console.log(age); // Output: 25

Why Is This Important for APIs?

APIs usually send data in the form of JSON. For example:

{
  "name": "John",
  "age": 25,
  "skills": ["JavaScript", "HTML", "CSS"]
}

When you receive this data in JavaScript, you’ll use arrays and objects to:

  1. Extract specific information.

  2. Modify or filter the data.

  3. Display it on a webpage.


Let’s learn more about what an (API) is.

An API (Application Programming Interface) is a set of rules and tools that allows one application to interact with another. Think of it as a middleman that helps two applications communicate.

In programming:

  • Your JavaScript code is the client.

  • The API specifies what kind of data or services you can request.

  • A remote server processes your request and sends back a respo


    Types of APIs

    1. Web APIs (Most common): Interact with servers over the web, usually using HTTP.

    2. Local APIs: Used by applications to communicate within a device.

    3. Library APIs: Allow interaction with libraries like DOM APIs in JavaScript.


How Web APIs Work

APIs usually follow the HTTP protocol and involve:

  1. Request: Your code sends a request to the API endpoint (a specific URL).

  2. Response: The server processes your request and sends back a response, typically in JSON format.


Important API Concepts

a. HTTP Methods

HTTP methods specify the type of operation:

  • GET: Retrieve data (most common).

  • POST: Send data to the server.

  • PUT: Update existing data.

  • DELETE: Remove data.

b. Endpoints

An endpoint is a URL where your request is sent. For example:

https://api.example.com/users

c. Status Codes

APIs send back HTTP status codes to tell you the result:

  • 200: Success.

  • 404: Not Found.

  • 500: Server Error.


JavaScript Basics for Working with APIs

To use APIs in JavaScript, you’ll primarily need:

  1. fetch() function: A built-in function to make HTTP requests.

  2. async/await: For handling asynchronous code.

  3. Promises: To work with responses.


    Using the fetch() Method

    Basic Syntax:

     fetch("API_URL")
       .then(response => response.json()) // Parse the response as JSON
       .then(data => console.log(data))  // Use the data
       .catch(error => console.error("Error:", error)); // Handle errors
    

    Step-by-Step Example: Fetching Data from an API

    Goal: Fetch user data from a sample API.

    1. API Endpoint:

       https://jsonplaceholder.typicode.com/users
      

      This API returns a list of user objects.

    2. JavaScript Code:

    // Step 1: Fetch data from the API
    fetch("https://jsonplaceholder.typicode.com/users")
      .then(response => {
        // Step 2: Check if the response is successful
        if (!response.ok) {
          throw new Error(`HTTP error! Status: ${response.status}`);
        }
        return response.json(); // Step 3: Parse the response as JSON
      })
      .then(data => {
        // Step 4: Use the received data
        console.log("User Data:", data);
      })
      .catch(error => {
        // Step 5: Handle any errors
        console.error("Error fetching data:", error);
      });
  1. What Happens Here?

    • fetch(): Sends a GET request to the API.

    • .then(response => response.json()): Converts the response to JSON.

    • .then(data => console.log(data)): Logs the data.

    • .catch(): Handles errors like network issues or invalid URLs.


Working with Asynchronous Code

Using async/await simplifies API calls.

Example:

        async function fetchUserData() {
          try {
            const response = await fetch("https://jsonplaceholder.typicode.com/users");
            if (!response.ok) {
              throw new Error(`HTTP error! Status: ${response.status}`);
            }
            const data = await response.json();
            console.log("User Data:", data);
          } catch (error) {
            console.error("Error fetching data:", error);
          }
        }

        fetchUserData();

Manipulating the API Data

Let’s say the API returned the following JSON:

        [
          { "id": 1, "name": "John Doe", "email": "john@example.com" },
          { "id": 2, "name": "Jane Smith", "email": "jane@example.com" }
        ]

Example: Extract User Emails

        fetch("https://jsonplaceholder.typicode.com/users")
          .then(response => response.json())
          .then(data => {
            const emails = data.map(user => user.email);
            console.log("User Emails:", emails); // Output: ["john@example.com", "jane@example.com"]
          });

Sending Data to an API (POST Request)

Example: Sending a New User

        const newUser = {
          name: "New User",
          email: "newuser@example.com",
        };

        async function createUser() {
          try {
            const response = await fetch("https://jsonplaceholder.typicode.com/users", {
              method: "POST", // HTTP method
              headers: {
                "Content-Type": "application/json", // Specify JSON format
              },
              body: JSON.stringify(newUser), // Convert JS object to JSON
            });

            const data = await response.json();
            console.log("Created User:", data);
          } catch (error) {
            console.error("Error creating user:", error);
          }
        }

        createUser();

Best Practices

  1. Read the API Documentation: Always check the API's documentation to know the available endpoints, parameters, and response structure.

  2. Handle Errors Gracefully: Use .catch() or try...catch to deal with errors.

  3. Secure API Keys: If the API requires an API key, never expose it in your front-end code.

  4. Optimize Requests: Avoid making unnecessary requests to reduce server load and improve performance.


    Hope that helps.