Category: JavaScript Miscellaneous

https://zain.sweetdishy.com/wp-content/uploads/2026/01/computing.png

  • JavaScript – Atomics Objects

    The Atomics object in JavaScript provides a set of static methods for performing atomic operations on SharedArrayBuffer objects. Atomic operations are operations that are guaranteed to be completed in a single step, without being interrupted by other threads. This makes them useful for implementing concurrent data structures and algorithms.

    The Atomics object in JavaScript, as part of the ECMAScript standard, serves as a crucial tool for managing shared memory in a multi-threaded environment. Let’s understand the basic concept of atomic operations in more detail:

    Atomics Object

    The Atomics object is a built-in JavaScript object that provides atomic operations on shared memory. It is designed to be used in a multi-threaded environment, where multiple threads or Web Workers may be concurrently accessing and modifying shared data.

    The Essence of “Atomic”

    In the context of the Atomics object, “atomic” signifies a crucial characteristic: it performs operations that are inherently indivisible. When we declare an operation as atomic; we imply its execution occurs continuously and uninterruptedly like a single unit. This quality is indispensable in preventing race conditions; these arise when concurrent operations’ outcomes depend on their timing and sequence of execution.

    Atomic Operations

    Atomic operations are low-level operations on shared memory that are guaranteed to be executed as a single, uninterruptible unit. These operations include additions, subtractions, bitwise operations, exchanges, and more.

    The Atomics object provides methods like add, sub, and, or, xor, load, store, exchange, and others, each corresponding to a specific atomic operation.

    Sr.No.Method & Description
    1Atomics.add()Adds a specified value to the element at the specified index in the typed array. Returns the original value atomically.
    2Atomics.sub()Subtracts a specified value from the element at the specified index in the typed array. Returns the original value atomically.
    3Atomics.and()Performs an atomic bitwise AND operation on the element at the specified index in the typed array with the given value. Returns the original value atomically.
    4Atomics.or()Performs an atomic bitwise OR operation on the element at the specified index in the typed array with the given value. Returns the original value atomically.
    5Atomics.xor()Performs an atomic bitwise XOR operation on the element at the specified index in the typed array with the given value. Returns the original value atomically.
    6Atomics.load()Retrieves the value at the specified index in the typed array atomically.
    7Atomics.store()Stores the given value at the specified index in the typed array atomically.
    8Atomics.exchange()Swaps the value at the specified index in the typed array with a specified value. Returns the original value atomically.
    9Atomics. compareExchange()Compares the value at the specified index in the typed array with a provided expected value, and if they match, updates the value with a new value. Returns the original value atomically.
    10Atomics.wait()Atomically waits for a value at the specified index in the typed array to be a specific value and then returns. Allows for efficient coordination between threads.
    11Atomics.notify()Atomically notifies the wait queue associated with the specified index in the typed array.

    Examples

    Example 1: Basic Usage of Atomics Operations

    In this example, the Atomics object is demonstrated for its fundamental atomic operations on shared memory. These operations include addition, subtraction, bitwise AND, OR, XOR, loading, storing, exchanging, and compare-exchanging values. Each operation ensures the indivisibility of the executed unit, crucial for preventing race conditions in a multi-threaded environment.

    Atomics.add()

    // Shared memory setupconst sharedBuffer =newSharedArrayBuffer(4);const sharedArray =newInt32Array(sharedBuffer);// Atomics.add()const originalAddValue = Atomics.add(sharedArray,0,10);
    console.log(`Atomics.add: Original value: ${originalAddValue}, New value: ${sharedArray[0]}`);

    Output

    Atomics.add: Original value: 0, New value: 10
    

    Atomics.add()

    // Shared memory setupconst sharedBuffer =newSharedArrayBuffer(4);const sharedArray =newInt32Array(sharedBuffer);// Atomics.sub()const originalSubValue = Atomics.sub(sharedArray,0,5);
    console.log(`Atomics.sub: Original value: ${originalSubValue}, New value: ${sharedArray[0]}`);

    Output

    Atomics.sub: Original value: 10, New value: 5
    

    Atomics.add()

    // Shared memory setupconst sharedBuffer =newSharedArrayBuffer(4);const sharedArray =newInt32Array(sharedBuffer);// Atomics.and()const originalAndValue = Atomics.and(sharedArray,0,0b1010);
    console.log(`Atomics.and: Original value: ${originalAndValue}, New value: ${sharedArray[0].toString(2)}`);

    Output

    Atomics.and: Original value: 5, New value: 0
    

    Atomics.or()

    // Shared memory setupconst sharedBuffer =newSharedArrayBuffer(4);const sharedArray =newInt32Array(sharedBuffer);// Atomics.or()const originalOrValue = Atomics.or(sharedArray,0,0b1100);
    console.log(`Atomics.or: Original value: ${originalOrValue}, New value: ${sharedArray[0].toString(2)}`);

    Output

    Atomics.or: Original value: 0, New value: 1100
    

    Atomics.xor()

    // Shared memory setupconst sharedBuffer =newSharedArrayBuffer(4);const sharedArray =newInt32Array(sharedBuffer);// Atomics.xor()const originalXorValue = Atomics.xor(sharedArray,0,0b0110);
    console.log(`Atomics.xor: Original value: ${originalXorValue}, New value: ${sharedArray[0].toString(2)}`);

    Output

    Atomics.xor: Original value: 12, New value: 1010
    

    Atomics.load()

    // Shared memory setupconst sharedBuffer =newSharedArrayBuffer(4);const sharedArray =newInt32Array(sharedBuffer);// Atomics.load()const loadedValue = Atomics.load(sharedArray,0);
    console.log(`Atomics.load: Loaded value: ${loadedValue}`);

    Output

    Atomics.load: Loaded value: 10
    

    Atomics.store()

    // Shared memory setupconst sharedBuffer =newSharedArrayBuffer(4);const sharedArray =newInt32Array(sharedBuffer);// Atomics.store()
    Atomics.store(sharedArray,0,42);
    console.log(`Atomics.store: New value: ${sharedArray[0]}`);

    Output

    Atomics.store: New value: 42
    

    Atomics.exchange()

    // Shared memory setupconst sharedBuffer =newSharedArrayBuffer(4);const sharedArray =newInt32Array(sharedBuffer);// Atomics.exchange()const originalExchangeValue = Atomics.exchange(sharedArray,0,99);
    console.log(`Atomics.exchange: Original value: ${originalExchangeValue}, New value: ${sharedArray[0]}`);

    Output

    Atomics.exchange: Original value: 42, New value: 99
    

    Atomics.compareExchange()

    // Shared memory setupconst sharedBuffer =newSharedArrayBuffer(4);const sharedArray =newInt32Array(sharedBuffer);// Atomics.compareExchange()const expectedValue =99;const newValue =55;const successfulCompareExchange = Atomics.compareExchange(sharedArray,0, expectedValue, newValue);
    console.log(`Atomics.compareExchange: Operation was${successfulCompareExchange ? ' ' : ' not '}successful. New value: ${sharedArray[0]}`);

    Output

    Atomics.compareExchange: Operation was successful. New value: 55
    

    Atomics.wait()

    // Shared memory setupconst sharedBuffer =newSharedArrayBuffer(4);const sharedArray =newInt32Array(sharedBuffer);// Atomics.wait()const valueToWaitFor =55;
    Atomics.store(sharedArray,0, valueToWaitFor);setTimeout(()=>{
        Atomics.notify(sharedArray,0);},2000);const waitResult = Atomics.wait(sharedArray,0, valueToWaitFor,5000);
    console.log(`Atomics.wait: Wait result: ${waitResult}`);

    Output

    Atomics.wait: Wait result: timed-out
    

    Example 2: Real-World Use Case – Synchronized Counter

    In this real-world scenario, we employ the Atomics object to construct a synchronized counter; multiple threads increment this counter through the use of the Atomics.add() operation, thus guaranteeing atomicity in our update process. The functionality and necessity for effective thread coordination become evident with such an application: it offers practical data management solutions within a multi-threaded environment.

    const sharedBuffer =newSharedArrayBuffer(4);const sharedArray =newInt32Array(sharedBuffer);// Synchronized counterfunctionincrementCounter(){const incrementValue =1;const originalValue = Atomics.add(sharedArray,0, incrementValue);
      console.log(`Incremented counter by ${incrementValue}. New value: ${sharedArray[0]}`);}// Multiple threads incrementing the countersetInterval(()=>{incrementCounter();},1000);// Simulate other activities in the main threadsetInterval(()=>{
      console.log('Main thread doing other work.');},3000);

    Output

    Incremented counter by 1. New value: 1
    Incremented counter by 1. New value: 2
    Main thread doing other work.
    Incremented counter by 1. New value: 3
    Incremented counter by 1. New value: 4
    Incremented counter by 1. New value: 5
    Main thread doing other work.
    Incremented counter by 1. New value: 6
    Incremented counter by 1. New value: 7
    Incremented counter by 1. New value: 8
    Main thread doing other work.
    ...
  • JavaScript – Async Iteration

    Asynchronous Iteration

    In JavaScript, asynchronous iteration refers to the ability to iterate over asynchronous sequences or collections, such as those returned by asynchronous functions or generators. Async iteration is typically used with operations that involve asynchronous tasks, such as fetching data from a remote server or reading from a file.

    Understanding Asynchronous Operations

    In basic terms, asynchronous operations in programming denote tasks or procedures that do not obstruct the program’s execution during their pending completion. Rather than pausing for each operation to conclude before proceeding onto the subsequent one; these asynchronous tasks enable a program: it continues executing other duties, concurrently waiting for the current task’s finalization.

    Using the ‘for await…of’ Loop

    The for await…of loop is used for asynchronous iteration. It works similarly to the regular for…of loop, but it is designed to work with asynchronous iterators. An asynchronous iterator is an object that defines an async next() method, which returns a promise for the next value in the sequence.

    Example: Using Promises

    JavaScript incorporates promises as a characteristic to manage asynchronous operations; these promises symbolize the potential outcomes, either completion or failure of an asynchronous task. Notably, the function asyncOperation emulates such tasks by returning a promise. The ‘for await…of’ loop elegantly navigates the asynchronous sequence, emphasizing promise utilization in managing non-blocking operations without compromising code lucidity.

    <!DOCTYPE html><html><body><h2>Async Iteration with Promises</h2><div id="output"></div><script>functionasyncOperation(value){returnnewPromise(resolve=>{setTimeout(()=>{
            document.getElementById('output').innerHTML +=`<p>Processed: ${value}</p>`;resolve(value);},1000);});}const asyncIterable ={[Symbol.asyncIterator]:asyncfunction*(){for(let i =1; i <=3; i++){yieldawaitasyncOperation(i);}},};asyncfunctionprocessAsyncIterable(){forawait(const result of asyncIterable){
          document.getElementById('output').innerHTML +=`<p>Received: ${result}</p>`;}}processAsyncIterable();</script></body></html>

    Example 2: Using Fetch API for Asynchronous HTTP Requests

    Here, we demonstrate asynchronous iteration with the Fetch API for executing HTTP requests: The asyncIterable operates to fetch data in an asynchronous manner. Furthermore; employing a ‘for await…of’ loop – it elegantly traverses through results showcasing how seamlessly async iteration amalgamates with external source data retrieval.

    <!DOCTYPE html><html><body><h2>Async Iteration with Fetch API</h2><div id="output"></div><script>const url ='https://jsonplaceholder.typicode.com/todos/';const asyncIterable ={[Symbol.asyncIterator]:asyncfunction*(){for(let i =1; i <=3; i++){const response =awaitfetch(`${url}${i}`);const data =await response.json();
            document.getElementById('output').innerHTML +=`<p>Received: ${JSON.stringify(data)}</p>`;yield data;}},};asyncfunctionprocessAsyncIterable(){forawait(const result of asyncIterable){// Already displaying results above, no need for additional output.}}processAsyncIterable();</script></body></html>

    Example 3: Using callback

    The approach employs a callback-based mechanism to achieve asynchronous iteration. The function asyncOperation imitates an asynchronous task and calls back upon completion. Meanwhile, the processAsyncIterable function actively iterates through an array, invoking the asynchronous operation for every element.

    <!DOCTYPE html><html><body><h2>Async Iteration with callback</h2><div id="output"></div><script>functionasyncOperation(value, callback){setTimeout(()=>{
          document.getElementById('output').innerHTML +=`<p>Processed: ${value}</p>`;callback(value);},1000);}functionprocessAsyncIterable(iterable, callback){const iterator = iterable[Symbol.iterator]();functioniterate(){const next = iterator.next();if(next.done){return;}const value = next.value;asyncOperation(value,result=>{
            document.getElementById('output').innerHTML +=`<p>Received: ${result}</p>`;iterate();});}iterate();}const asyncIterable =[5,6,7,8,9,10];processAsyncIterable(asyncIterable,result=>{// You can handle final result or additional actions here if needed.});</script></body></html>

    Example 4: Promise With Error

    The method .then() in JavaScript employs one or two callback functions to manage the successful resolution of a Promise: upon the promise’s resolution, it executes its first function; should rejection occur an optional second function is then executed.

    The method .catch() accompanies Promises, specifically to address promise rejections. A single callback function executes upon the rejection of the promise; this provides an elegant solution for managing errors in asynchronous operations – eliminating the need for a distinct .then() block dedicated to error handling.

    <!DOCTYPE html><html><head><style>
        #output {
          margin-top:20px;}</style></head><body><h2>Async Iteration with Promises</h2><button onclick="startAsyncIteration()">Start Async Iteration</button><div id="output"></div><script>functiondelay(ms){returnnewPromise(resolve=>setTimeout(resolve, ms));}functionfetchData(index){returnnewPromise((resolve, reject)=>{if(index <5){delay(1000).then(()=>resolve(`Data ${index}`));}else{// Simulate an error for index 5reject(newError('Error fetching data for index 5'));}});}functionstartAsyncIteration(){
        document.getElementById('output').innerHTML ='';let index =0;functioniterate(){fetchData(index).then(data=>{displayData(data);
              index++;if(index <6){iterate();}}).catch(error=>{// Display error on the page.displayError(error.message);});}iterate();}functiondisplayData(data){const outputDiv = document.getElementById('output');
        outputDiv.innerHTML +=`<p>Data received: ${data}</p>`;}functiondisplayError(errorMessage){const outputDiv = document.getElementById('output');
        outputDiv.innerHTML +=`<p style="color: red;">Error: ${errorMessage}</p>`;}</script></body></html>

    Real World Use Cases

    In real-world scenarios, we apply JavaScript async iterations to optimize various asynchronous operations: fetching data concurrently from multiple APIs in web applications; processing real-time updates – a function critical for chat systems and executing batch tasks or parallel tasks that require intensive resources. Furthermore, managing file operations and streams is possible with this technique along with handling concurrent user interactions on interactive web pages. Other applications involve processing data from IoT devices dynamically loading content onto webpages, these too benefit greatly from the use of asynchronous iteration due to their need for non-blocking efficiency as well responsiveness when dealing with complex task management such as offline-first application’s data synchronization.

  • JavaScript – Ajax

    Asynchronous JavaScript and XML (Ajax) represents a web development technique: it enables dynamic, interactive communication between server and webpage without necessitating complete page reload. The descriptor “asynchronous” underlines that data exchanges can occur in the background, independent of user experience disruption. Rather than idly awaiting full-page refreshment; Ajax empowers real-time updates on specific sections of a webpage, thus yielding an interface that is more seamless and responsive.

    How Ajax works?

    The central role in enabling dynamic updates, without the necessity of a full page reload, belongs to the XMLHttpRequest object within JavaScript’s Ajax functionality. This particular process allows for asynchronous communication between server and web page. The server responds with data, usually in JSON or XML format when receiving a request sent by this object. Processing this data is the task of JavaScript; it updates specific portions of the webpage in real-time. The asynchronous nature which is a critical feature for modern web development ensures these operations occur unobtrusively in background, thereby enhancing interactivity by allowing data to be fetched and sent asynchronously.

    Here, we will to explore Ajax to get a deeper understanding of it.

    There are 4 approaches to make Ajax calls or to implement Ajax in JavaScript and they are:

    • XMLHttpRequest (Older Approach)
    • Fetch API (Modern Approach)
    • Axios (Library for HTTP Requests)
    • jQuery Ajax

    We will be using JSONPlaceholder in all the examples for understanding purposes.

    JSONPlaceholder is an open-source and simulated REST API provider which lets developers test their prototype applications. It returns fake/dummy data for various resources like users, posts, comments etc. The API endpoints of JSONPlaceholder can be made using HTTP requests and they will be mimicking the nature of real APIs without any need for authentication. Our goal here is to use these APIs/endpoints to under Javascript-Ajax.

    Using XMLHttpRequest

    The Native JavaScript approach using XMLHttpRequest represents the oldest method for asynchronous requests. It relies on the XMLHttpRequest object to create and send HTTP requests. This method involves setting up callback functions to handle various states of the request, making it suitable for simpler scenarios. However, it has some limitations compared to more modern approaches.

    Example

    <!DOCTYPE html><html lang="en"><body><p>Native XMLHttpRequest Example</p><button onclick="nativeAjax()">Make Request</button><pre id="result"></pre><script>functionnativeAjax(){var xhr =newXMLHttpRequest();
        xhr.open('GET','https://jsonplaceholder.typicode.com/users/2',true);
        xhr.onreadystatechange=function(){if(xhr.readyState ==4&& xhr.status ==200){var responseData =JSON.stringify(JSON.parse(xhr.responseText),null,2);
            document.getElementById('result').innerText ='Native XMLHttpRequest:\n'+ responseData;}};
        xhr.send();}</script></body></html>

    Using Fetch API

    Presenting a modern alternative to XMLHttpRequest, the Fetch API offers a more straightforward and powerful syntax; it returns Promises thus enhancing the intuitive handling of asynchronous operations. Supporting an extensive array of HTTP methods and headers: this provides developers with a cleaner, concise method for making asynchronous requests. Contemporary JavaScript applications often prefer it for its clarity and ease of use.

    Example

    <!DOCTYPE html><html><body><h1>Fetch API Example</h1><button onclick="fetchApi()">Make Request</button><pre id="result"></pre><script>functionfetchApi(){fetch('https://jsonplaceholder.typicode.com/users/3').then(response=>{if(!response.ok){thrownewError('Network response was not ok');}return response.json();}).then(data=>{var formattedData =JSON.stringify(data,null,2);
            document.getElementById('result').innerText ='Fetch API:\n'+ formattedData;}).catch(error=>{
            document.getElementById('result').innerText ='Fetch API Error: '+ error.message;});}</script></body></html>

    Using Axios

    Designed for making HTTP requests, Axios emerges as a popular JavaScript library. Its popularity is largely due to its clean and concise syntax: built on Promises; furthermore, it boasts automatic JSON data transformation support features that set it apart from other libraries in the field. Offering more than just basic functionality, Axios presents advanced features such as request and response interceptors, a robust selection for managing AJAX operations within the context of modern web development environment.

    Example

    <!DOCTYPE html><html><head><script src="https://cdn.jsdelivr.net/npm/axios/dist/axios.min.js"></script></head><body><h1>Axios Example</h1><button onclick="axiosExample()">Make Request</button><pre id="result3"></pre><script>functionaxiosExample(){
        axios.get('https://jsonplaceholder.typicode.com/users/5').then(response=>{var formattedData =JSON.stringify(response.data,null,2);
            document.getElementById('result3').innerText ='Axios:\n'+ formattedData;}).catch(error=>{
            document.getElementById('result3').innerText ='Axios Error: '+ error.message;});}</script></body></html>

    Using Ajax jQuery

    The $.ajax method in jQuery simplifies the AJAX request process: a popular approach previously; however, its usage has waned alongside modern JavaScript’s ascent. Offering an interface that is both consistent and cross-browser compatible, jQuery Ajax remains suitable for projects already using or needing specific features of jQuery due to these advantages it presents. However, for new projects, modern alternatives may be preferred.

    Example

    <!DOCTYPE html><html><head><script src="https://code.jquery.com/jquery-3.6.4.min.js"></script></head><body><h1>jQuery Ajax Example</h1><button onclick="jqueryAjax()">Make Request</button><pre id="result4"></pre><script>functionjqueryAjax(){
        $.ajax({
          url:'https://jsonplaceholder.typicode.com/users/7',
          method:'GET',
          dataType:'json',success:function(data){var formattedData =JSON.stringify(data,null,2);
            document.getElementById('result4').innerText ='jQuery Ajax:\n'+ formattedData;},error:function(xhr, status, error){
            document.getElementById('result4').innerText ='jQuery Ajax Error: '+ error;}});}</script></body></html>

    Ajax Use Cases

    In real-world scenarios, developers commonly employ Ajax to create web applications that are both responsive and interactive. A pertinent example: a social media platform; here, users have the ability – thanks to Ajax, to add or load new comments in the background without needing an entire page refresh. Dynamic updating ensures a user experience that is smooth and uninterrupted, permitting individuals to engage with content and one another seamlessly. This process yields a platform more responsive and engaging; it amplifies user interaction thus enhancing satisfaction.

    Prominent companies utilizing Ajax for enhanced user experiences include Google (Gmail, Maps), Facebook, Twitter, Amazon, Netflix, GitHub, LinkedIn, YouTube, Microsoft Office Online, and Uber. Ajax is employed for real-time updates, dynamic content loading, and seamless interactions on their respective platforms.