ಕನ್ನಡ

ಜಾವಾಸ್ಕ್ರಿಪ್ಟ್‌ನ ಅಬೋರ್ಟ್‌ಕಂಟ್ರೋಲರ್ ಬಳಸಿ ಫೆಚ್ ವಿನಂತಿಗಳು, ಟೈಮರ್‌ಗಳು, ಮತ್ತು ಇತರ ಅಸಿಂಕ್ರೋನಸ್ ಕಾರ್ಯಾಚರಣೆಗಳನ್ನು ಪರಿಣಾಮಕಾರಿಯಾಗಿ ರದ್ದುಗೊಳಿಸುವುದು ಹೇಗೆಂದು ತಿಳಿಯಿರಿ, ಇದು ಸ್ವಚ್ಛ ಮತ್ತು ಉತ್ತಮ ಕಾರ್ಯಕ್ಷಮತೆಯ ಕೋಡ್‌ಗೆ ದಾರಿ ಮಾಡುತ್ತದೆ.

ಜಾವಾಸ್ಕ್ರಿಪ್ಟ್ ಅಬೋರ್ಟ್‌ಕಂಟ್ರೋಲರ್: ಅಸಿಂಕ್ರೋನಸ್ ಆಪರೇಷನ್‌ಗಳನ್ನು ರದ್ದುಗೊಳಿಸುವಲ್ಲಿ ಪರಿಣತಿ

ಆಧುನಿಕ ವೆಬ್ ಡೆವಲಪ್‌ಮೆಂಟ್‌ನಲ್ಲಿ, ಅಸಿಂಕ್ರೋನಸ್ ಆಪರೇಷನ್‌ಗಳು ಸರ್ವೇಸಾಮಾನ್ಯ. APIಗಳಿಂದ ಡೇಟಾ ಪಡೆಯುವುದು, ಟೈಮರ್‌ಗಳನ್ನು ಹೊಂದಿಸುವುದು, ಮತ್ತು ಬಳಕೆದಾರರ ಸಂವಾದಗಳನ್ನು ನಿರ್ವಹಿಸುವುದು ಇವೆಲ್ಲವೂ ಸ್ವತಂತ್ರವಾಗಿ ಮತ್ತು ದೀರ್ಘಕಾಲದವರೆಗೆ ನಡೆಯುವ ಕೋಡ್ ಅನ್ನು ಒಳಗೊಂಡಿರುತ್ತವೆ. ಆದಾಗ್ಯೂ, ಈ ಆಪರೇಷನ್‌ಗಳು ಪೂರ್ಣಗೊಳ್ಳುವ ಮೊದಲೇ ಅವುಗಳನ್ನು ರದ್ದುಗೊಳಿಸಬೇಕಾದ ಸಂದರ್ಭಗಳಿವೆ. ಇಲ್ಲಿಯೇ ಜಾವಾಸ್ಕ್ರಿಪ್ಟ್‌ನಲ್ಲಿನ AbortController ಇಂಟರ್ಫೇಸ್ ರಕ್ಷಣೆಗೆ ಬರುತ್ತದೆ. ಇದು DOM ಆಪರೇಷನ್‌ಗಳು ಮತ್ತು ಇತರ ಅಸಿಂಕ್ರೋನಸ್ ಕಾರ್ಯಗಳಿಗೆ ರದ್ದತಿ ವಿನಂತಿಗಳನ್ನು ಸಂಕೇತಿಸಲು ಸ್ವಚ್ಛ ಮತ್ತು ಸಮರ್ಥವಾದ ಮಾರ್ಗವನ್ನು ಒದಗಿಸುತ್ತದೆ.

ರದ್ದುಗೊಳಿಸುವಿಕೆಯ ಅಗತ್ಯವನ್ನು ಅರ್ಥಮಾಡಿಕೊಳ್ಳುವುದು

ತಾಂತ್ರಿಕ ವಿವರಗಳಿಗೆ ಹೋಗುವ ಮೊದಲು, ಅಸಿಂಕ್ರೋನಸ್ ಆಪರೇಷನ್‌ಗಳನ್ನು ರದ್ದುಗೊಳಿಸುವುದು ಏಕೆ ಮುಖ್ಯ ಎಂಬುದನ್ನು ಅರ್ಥಮಾಡಿಕೊಳ್ಳೋಣ. ಈ ಸಾಮಾನ್ಯ ಸನ್ನಿವೇಶಗಳನ್ನು ಪರಿಗಣಿಸಿ:

ಅಬೋರ್ಟ್‌ಕಂಟ್ರೋಲರ್ ಮತ್ತು ಅಬೋರ್ಟ್‌ಸಿಗ್ನಲ್ ಪರಿಚಯ

AbortController ಇಂಟರ್ಫೇಸ್ ಅಸಿಂಕ್ರೋನಸ್ ಆಪರೇಷನ್‌ಗಳನ್ನು ರದ್ದುಗೊಳಿಸುವ ಸಮಸ್ಯೆಯನ್ನು ಪರಿಹರಿಸಲು ವಿನ್ಯಾಸಗೊಳಿಸಲಾಗಿದೆ. ಇದು ಎರಡು ಪ್ರಮುಖ ಅಂಶಗಳನ್ನು ಒಳಗೊಂಡಿದೆ:

ಮೂಲ ಬಳಕೆ: ಫೆಚ್ ವಿನಂತಿಗಳನ್ನು ರದ್ದುಗೊಳಿಸುವುದು

ಒಂದು fetch ವಿನಂತಿಯನ್ನು ರದ್ದುಗೊಳಿಸುವ ಸರಳ ಉದಾಹರಣೆಯೊಂದಿಗೆ ಪ್ರಾರಂಭಿಸೋಣ:


const controller = new AbortController();
const signal = controller.signal;

fetch('https://api.example.com/data', { signal })
  .then(response => {
    if (!response.ok) {
      throw new Error(`HTTP error! Status: ${response.status}`);
    }
    return response.json();
  })
  .then(data => {
    console.log('Data:', data);
  })
  .catch(error => {
    if (error.name === 'AbortError') {
      console.log('Fetch aborted');
    } else {
      console.error('Fetch error:', error);
    }
  });

// To cancel the fetch request:
controller.abort();

ವಿವರಣೆ:

  1. ನಾವು AbortController ಇನ್‌ಸ್ಟಾನ್ಸ್ ಅನ್ನು ರಚಿಸುತ್ತೇವೆ.
  2. ನಾವು controller ನಿಂದ ಸಂಬಂಧಿತ AbortSignal ಅನ್ನು ಪಡೆಯುತ್ತೇವೆ.
  3. ನಾವು signal ಅನ್ನು fetch ಆಯ್ಕೆಗಳಿಗೆ ರವಾನಿಸುತ್ತೇವೆ.
  4. ನಮಗೆ ವಿನಂತಿಯನ್ನು ರದ್ದುಗೊಳಿಸಬೇಕಾದರೆ, ನಾವು controller.abort() ಅನ್ನು ಕರೆಯುತ್ತೇವೆ.
  5. .catch() ಬ್ಲಾಕ್‌ನಲ್ಲಿ, ಎರರ್ AbortError ಆಗಿದೆಯೇ ಎಂದು ನಾವು ಪರಿಶೀಲಿಸುತ್ತೇವೆ. ಹಾಗಿದ್ದರೆ, ವಿನಂತಿಯು ರದ್ದುಗೊಂಡಿದೆ ಎಂದು ನಮಗೆ ತಿಳಿಯುತ್ತದೆ.

ಅಬೋರ್ಟ್‌ಎರರ್ ಅನ್ನು ನಿಭಾಯಿಸುವುದು

controller.abort() ಅನ್ನು ಕರೆದಾಗ, fetch ವಿನಂತಿಯು AbortError ನೊಂದಿಗೆ ತಿರಸ್ಕರಿಸಲ್ಪಡುತ್ತದೆ. ನಿಮ್ಮ ಕೋಡ್‌ನಲ್ಲಿ ಈ ಎರರ್ ಅನ್ನು ಸೂಕ್ತವಾಗಿ ನಿಭಾಯಿಸುವುದು ಬಹಳ ಮುಖ್ಯ. ಹಾಗೆ ಮಾಡಲು ವಿಫಲವಾದರೆ, ಹ್ಯಾಂಡಲ್ ಮಾಡದ ಪ್ರಾಮಿಸ್ ರಿಜೆಕ್ಷನ್‌ಗಳು ಮತ್ತು ಅನಿರೀಕ್ಷಿತ ವರ್ತನೆಗೆ ಕಾರಣವಾಗಬಹುದು.

ಎರರ್ ಹ್ಯಾಂಡ್ಲಿಂಗ್‌ನೊಂದಿಗೆ ಹೆಚ್ಚು ದೃಢವಾದ ಉದಾಹರಣೆ ಇಲ್ಲಿದೆ:


const controller = new AbortController();
const signal = controller.signal;

async function fetchData() {
  try {
    const response = await fetch('https://api.example.com/data', { signal });
    if (!response.ok) {
      throw new Error(`HTTP error! Status: ${response.status}`);
    }
    const data = await response.json();
    console.log('Data:', data);
    return data;
  } catch (error) {
    if (error.name === 'AbortError') {
      console.log('Fetch aborted');
      return null; // Or throw the error to be handled further up
    } else {
      console.error('Fetch error:', error);
      throw error; // Re-throw the error to be handled further up
    }
  }
}

fetchData();

// To cancel the fetch request:
controller.abort();

ಅಬೋರ್ಟ್‌ಎರರ್ ನಿಭಾಯಿಸಲು ಉತ್ತಮ ಅಭ್ಯಾಸಗಳು:

ಅಬೋರ್ಟ್‌ಸಿಗ್ನಲ್‌ನೊಂದಿಗೆ ಟೈಮರ್‌ಗಳನ್ನು ರದ್ದುಗೊಳಿಸುವುದು

setTimeout ಅಥವಾ setInterval ನೊಂದಿಗೆ ರಚಿಸಲಾದ ಟೈಮರ್‌ಗಳನ್ನು ರದ್ದುಗೊಳಿಸಲು AbortSignal ಅನ್ನು ಸಹ ಬಳಸಬಹುದು. ಇದಕ್ಕೆ ಸ್ವಲ್ಪ ಹೆಚ್ಚು ಹಸ್ತಚಾಲಿತ ಕೆಲಸದ ಅಗತ್ಯವಿದೆ, ಏಕೆಂದರೆ ಅಂತರ್ನಿರ್ಮಿತ ಟೈಮರ್ ಫಂಕ್ಷನ್‌ಗಳು ನೇರವಾಗಿ AbortSignal ಅನ್ನು ಬೆಂಬಲಿಸುವುದಿಲ್ಲ. ಅಬೋರ್ಟ್ ಸಿಗ್ನಲ್‌ಗಾಗಿ ಕಾಯುವ ಮತ್ತು ಅದು ಪ್ರಚೋದಿಸಲ್ಪಟ್ಟಾಗ ಟೈಮರ್ ಅನ್ನು ತೆರವುಗೊಳಿಸುವ ಕಸ್ಟಮ್ ಫಂಕ್ಷನ್ ಅನ್ನು ನೀವು ರಚಿಸಬೇಕಾಗಿದೆ.


function cancellableTimeout(callback, delay, signal) {
  let timeoutId;

  const timeoutPromise = new Promise((resolve, reject) => {
    timeoutId = setTimeout(() => {
      resolve(callback());
    }, delay);

    signal.addEventListener('abort', () => {
      clearTimeout(timeoutId);
      reject(new Error('Timeout Aborted'));
    });
  });

  return timeoutPromise;
}

const controller = new AbortController();
const signal = controller.signal;


cancellableTimeout(() => {
  console.log('Timeout executed');
}, 2000, signal)
.then(() => console.log("Timeout finished successfully"))
.catch(err => console.log(err));

// To cancel the timeout:
controller.abort();

ವಿವರಣೆ:

  1. cancellableTimeout ಫಂಕ್ಷನ್ ಕಾಲ್‌ಬ್ಯಾಕ್, ವಿಳಂಬ (delay), ಮತ್ತು AbortSignal ಅನ್ನು ಆರ್ಗ್ಯುಮೆಂಟ್‌ಗಳಾಗಿ ತೆಗೆದುಕೊಳ್ಳುತ್ತದೆ.
  2. ಇದು setTimeout ಅನ್ನು ಹೊಂದಿಸುತ್ತದೆ ಮತ್ತು ಟೈಮ್‌ಔಟ್ ಐಡಿಯನ್ನು ಸಂಗ್ರಹಿಸುತ್ತದೆ.
  3. ಇದು AbortSignal ಗೆ abort ಈವೆಂಟ್‌ಗಾಗಿ ಕಾಯುವ ಇವೆಂಟ್ ಲಿಸನರ್ ಅನ್ನು ಸೇರಿಸುತ್ತದೆ.
  4. abort ಈವೆಂಟ್ ಪ್ರಚೋದಿಸಲ್ಪಟ್ಟಾಗ, ಇವೆಂಟ್ ಲಿಸನರ್ ಟೈಮ್‌ಔಟ್ ಅನ್ನು ತೆರವುಗೊಳಿಸುತ್ತದೆ ಮತ್ತು ಪ್ರಾಮಿಸ್ ಅನ್ನು ತಿರಸ್ಕರಿಸುತ್ತದೆ.

ಇವೆಂಟ್ ಲಿಸನರ್‌ಗಳನ್ನು ರದ್ದುಗೊಳಿಸುವುದು

ಟೈಮರ್‌ಗಳಂತೆಯೇ, ಇವೆಂಟ್ ಲಿಸನರ್‌ಗಳನ್ನು ರದ್ದುಗೊಳಿಸಲು ನೀವು AbortSignal ಅನ್ನು ಬಳಸಬಹುದು. ಅನ್‌ಮೌಂಟ್ ಆಗುತ್ತಿರುವ ಕಾಂಪೊನೆಂಟ್‌ಗೆ ಸಂಬಂಧಿಸಿದ ಇವೆಂಟ್ ಲಿಸನರ್‌ಗಳನ್ನು ತೆಗೆದುಹಾಕಲು ನೀವು ಬಯಸಿದಾಗ ಇದು ವಿಶೇಷವಾಗಿ ಉಪಯುಕ್ತವಾಗಿದೆ.


const controller = new AbortController();
const signal = controller.signal;

const button = document.getElementById('myButton');

button.addEventListener('click', () => {
  console.log('Button clicked!');
}, { signal });

// To cancel the event listener:
controller.abort();

ವಿವರಣೆ:

  1. ನಾವು addEventListener ಮೆಥಡ್‌ಗೆ signal ಅನ್ನು ಆಯ್ಕೆಯಾಗಿ ರವಾನಿಸುತ್ತೇವೆ.
  2. controller.abort() ಅನ್ನು ಕರೆದಾಗ, ಇವೆಂಟ್ ಲಿಸನರ್ ಸ್ವಯಂಚಾಲಿತವಾಗಿ ತೆಗೆದುಹಾಕಲ್ಪಡುತ್ತದೆ.

ರಿಯಾಕ್ಟ್ ಕಾಂಪೊನೆಂಟ್‌ಗಳಲ್ಲಿ ಅಬೋರ್ಟ್‌ಕಂಟ್ರೋಲರ್

ರಿಯಾಕ್ಟ್‌ನಲ್ಲಿ, ಕಾಂಪೊನೆಂಟ್ ಅನ್‌ಮೌಂಟ್ ಆದಾಗ ಅಸಿಂಕ್ರೋನಸ್ ಆಪರೇಷನ್‌ಗಳನ್ನು ರದ್ದುಗೊಳಿಸಲು ನೀವು AbortController ಅನ್ನು ಬಳಸಬಹುದು. ಇದು ಮೆಮೊರಿ ಲೀಕ್‌ಗಳು ಮತ್ತು ಅನ್‌ಮೌಂಟ್ ಆದ ಕಾಂಪೊನೆಂಟ್‌ಗಳನ್ನು ಅಪ್‌ಡೇಟ್ ಮಾಡುವುದರಿಂದ ಉಂಟಾಗುವ ದೋಷಗಳನ್ನು ತಡೆಯಲು ಅತ್ಯಗತ್ಯ. useEffect ಹುಕ್ ಬಳಸಿ ಒಂದು ಉದಾಹರಣೆ ಇಲ್ಲಿದೆ:


import React, { useState, useEffect } from 'react';

function MyComponent() {
  const [data, setData] = useState(null);

  useEffect(() => {
    const controller = new AbortController();
    const signal = controller.signal;

    async function fetchData() {
      try {
        const response = await fetch('https://api.example.com/data', { signal });
        if (!response.ok) {
          throw new Error(`HTTP error! Status: ${response.status}`);
        }
        const data = await response.json();
        setData(data);
      } catch (error) {
        if (error.name === 'AbortError') {
          console.log('Fetch aborted');
        } else {
          console.error('Fetch error:', error);
        }
      }
    }

    fetchData();

    return () => {
      controller.abort(); // Cancel the fetch request when the component unmounts
    };
  }, []); // Empty dependency array ensures this effect runs only once on mount

  return (
    
{data ? (

Data: {JSON.stringify(data)}

) : (

Loading...

)}
); } export default MyComponent;

ವಿವರಣೆ:

  1. ನಾವು useEffect ಹುಕ್‌ನೊಳಗೆ AbortController ಅನ್ನು ರಚಿಸುತ್ತೇವೆ.
  2. ನಾವು signal ಅನ್ನು fetch ವಿನಂತಿಗೆ ರವಾನಿಸುತ್ತೇವೆ.
  3. ನಾವು useEffect ಹುಕ್‌ನಿಂದ ಕ್ಲೀನಪ್ ಫಂಕ್ಷನ್ ಅನ್ನು ಹಿಂತಿರುಗಿಸುತ್ತೇವೆ. ಈ ಫಂಕ್ಷನ್ ಕಾಂಪೊನೆಂಟ್ ಅನ್‌ಮೌಂಟ್ ಆದಾಗ ಕರೆಯಲ್ಪಡುತ್ತದೆ.
  4. ಕ್ಲೀನಪ್ ಫಂಕ್ಷನ್‌ನೊಳಗೆ, ಫೆಚ್ ವಿನಂತಿಯನ್ನು ರದ್ದುಗೊಳಿಸಲು ನಾವು controller.abort() ಅನ್ನು ಕರೆಯುತ್ತೇವೆ.

ಸುಧಾರಿತ ಬಳಕೆಯ ಪ್ರಕರಣಗಳು

ಅಬೋರ್ಟ್‌ಸಿಗ್ನಲ್‌ಗಳನ್ನು ಚೈನ್ ಮಾಡುವುದು

ಕೆಲವೊಮ್ಮೆ, ನೀವು ಅನೇಕ AbortSignal ಗಳನ್ನು ಒಟ್ಟಿಗೆ ಚೈನ್ ಮಾಡಲು ಬಯಸಬಹುದು. ಉದಾಹರಣೆಗೆ, ಪೋಷಕ ಕಾಂಪೊನೆಂಟ್ ತನ್ನ ಚೈಲ್ಡ್ ಕಾಂಪೊನೆಂಟ್‌ಗಳಲ್ಲಿನ ಆಪರೇಷನ್‌ಗಳನ್ನು ರದ್ದುಗೊಳಿಸಬೇಕಾಗಬಹುದು. ಹೊಸ AbortController ಅನ್ನು ರಚಿಸಿ ಮತ್ತು ಅದರ ಸಿಗ್ನಲ್ ಅನ್ನು ಪೋಷಕ ಮತ್ತು ಚೈಲ್ಡ್ ಕಾಂಪೊನೆಂಟ್‌ಗಳಿಗೆ ರವಾನಿಸುವ ಮೂಲಕ ನೀವು ಇದನ್ನು ಸಾಧಿಸಬಹುದು.

ಥರ್ಡ್-ಪಾರ್ಟಿ ಲೈಬ್ರರಿಗಳೊಂದಿಗೆ ಅಬೋರ್ಟ್‌ಕಂಟ್ರೋಲರ್ ಬಳಸುವುದು

ನೀವು ನೇರವಾಗಿ AbortSignal ಅನ್ನು ಬೆಂಬಲಿಸದ ಥರ್ಡ್-ಪಾರ್ಟಿ ಲೈಬ್ರರಿಯನ್ನು ಬಳಸುತ್ತಿದ್ದರೆ, ಲೈಬ್ರರಿಯ ರದ್ದತಿ ಯಾಂತ್ರಿಕತೆಯೊಂದಿಗೆ ಕೆಲಸ ಮಾಡಲು ನಿಮ್ಮ ಕೋಡ್ ಅನ್ನು ನೀವು ಹೊಂದಿಕೊಳ್ಳಬೇಕಾಗಬಹುದು. ಇದು AbortSignal ಅನ್ನು ನಿಭಾಯಿಸುವ ನಿಮ್ಮ ಸ್ವಂತ ಫಂಕ್ಷನ್‌ಗಳಲ್ಲಿ ಲೈಬ್ರರಿಯ ಅಸಿಂಕ್ರೋನಸ್ ಫಂಕ್ಷನ್‌ಗಳನ್ನು ಸುತ್ತುವುದನ್ನು ಒಳಗೊಂಡಿರಬಹುದು.

ಅಬೋರ್ಟ್‌ಕಂಟ್ರೋಲರ್ ಬಳಸುವುದರ ಪ್ರಯೋಜನಗಳು

ಬ್ರೌಸರ್ ಹೊಂದಾಣಿಕೆ

AbortController ಕ್ರೋಮ್, ಫೈರ್‌ಫಾಕ್ಸ್, ಸಫಾರಿ, ಮತ್ತು ಎಡ್ಜ್ ಸೇರಿದಂತೆ ಆಧುನಿಕ ಬ್ರೌಸರ್‌ಗಳಲ್ಲಿ ವ್ಯಾಪಕವಾಗಿ ಬೆಂಬಲಿತವಾಗಿದೆ. ಇತ್ತೀಚಿನ ಮಾಹಿತಿಗಾಗಿ ನೀವು MDN ವೆಬ್ ಡಾಕ್ಸ್‌ನಲ್ಲಿ ಹೊಂದಾಣಿಕೆ ಟೇಬಲ್ ಅನ್ನು ಪರಿಶೀಲಿಸಬಹುದು.

ಪಾಲಿಫಿಲ್‌ಗಳು

AbortController ಅನ್ನು ಸ್ಥಳೀಯವಾಗಿ ಬೆಂಬಲಿಸದ ಹಳೆಯ ಬ್ರೌಸರ್‌ಗಳಿಗಾಗಿ, ನೀವು ಪಾಲಿಫಿಲ್ ಅನ್ನು ಬಳಸಬಹುದು. ಪಾಲಿಫಿಲ್ ಎನ್ನುವುದು ಹಳೆಯ ಬ್ರೌಸರ್‌ಗಳಲ್ಲಿ ಹೊಸ ವೈಶಿಷ್ಟ್ಯದ ಕಾರ್ಯವನ್ನು ಒದಗಿಸುವ ಕೋಡ್‌ನ ತುಣುಕು. ಆನ್‌ಲೈನ್‌ನಲ್ಲಿ ಹಲವಾರು AbortController ಪಾಲಿಫಿಲ್‌ಗಳು ಲಭ್ಯವಿದೆ.

ತೀರ್ಮಾನ

AbortController ಇಂಟರ್ಫೇಸ್ ಜಾವಾಸ್ಕ್ರಿಪ್ಟ್‌ನಲ್ಲಿ ಅಸಿಂಕ್ರೋನಸ್ ಆಪರೇಷನ್‌ಗಳನ್ನು ನಿರ್ವಹಿಸಲು ಒಂದು ಶಕ್ತಿಯುತ ಸಾಧನವಾಗಿದೆ. AbortController ಅನ್ನು ಬಳಸುವ ಮೂಲಕ, ನೀವು ರದ್ದತಿಯನ್ನು ಸುಲಲಿತವಾಗಿ ನಿಭಾಯಿಸುವ ಸ್ವಚ್ಛ, ಹೆಚ್ಚು ಕಾರ್ಯಕ್ಷಮತೆಯ, ಮತ್ತು ಹೆಚ್ಚು ದೃಢವಾದ ಕೋಡ್ ಅನ್ನು ಬರೆಯಬಹುದು. ನೀವು APIಗಳಿಂದ ಡೇಟಾ ಪಡೆಯುತ್ತಿರಲಿ, ಟೈಮರ್‌ಗಳನ್ನು ಹೊಂದಿಸುತ್ತಿರಲಿ, ಅಥವಾ ಇವೆಂಟ್ ಲಿಸನರ್‌ಗಳನ್ನು ನಿರ್ವಹಿಸುತ್ತಿರಲಿ, AbortController ನಿಮ್ಮ ವೆಬ್ ಅಪ್ಲಿಕೇಶನ್‌ಗಳ ಒಟ್ಟಾರೆ ಗುಣಮಟ್ಟವನ್ನು ಸುಧಾರಿಸಲು ಸಹಾಯ ಮಾಡುತ್ತದೆ.

ಹೆಚ್ಚಿನ ಓದು