Free tutorials & notes in Hindi & English · Clean code examples 🧰 मुफ़्त PDF और फ़ोटो टूल्स →
⚡ Days 15–22 – Advanced और Async JavaScript  ·  दिन 20

दिन 20: async/await और fetch: APIs के साथ काम

⏱ 110 min📶 Intermediate → Pro🎯 100% self-study
दिन 20 / 30

✅ आज आप सीखेंगे

  • async functions और await
  • try/catch/finally से error handling
  • fetch: GET, response.ok, status codes, JSON
  • UI में loading, empty और error states
  • JSON POST, validation errors, timeouts और parallel requests संभालना

🏢 असली दुनिया में

अब तक products हमारे JavaScript में लिखे थे। असली दुकानें उन्हें server से load करती हैं ताकि मालिक developer के बिना prices बदल सके। इस course के लिए हमने मुफ़्त practice API बनाया है codingeasily.in/api/sweets/ – यह असली JSON लौटाता है, search support करता है, धीमा (?delay=2000) या ख़राब (?fail=1) किया जा सकता है, और orders validate करता है। आज आप professional front-end developer की तरह इससे जुड़ेंगे।

async और await

JavaScript
const wait = (ms, value) => new Promise(r => setTimeout(() => r(value), ms));
const getUser = id => wait(50, { id, name: 'Aarti' });
const getOrders = user => wait(50, [{ id: 1042, total: 1800 }]);

// Same flow as yesterday’s promise chain – but reads top to bottom
async function showLastOrder(userId) {
  const user = await getUser(userId);         // pause here until the promise settles
  const orders = await getOrders(user);
  return `${user.name}: last order #${orders[0].id} (₹${orders[0].total})`;
}

showLastOrder(7).then(console.log);           // an async function ALWAYS returns a promise
console.log('This line runs first – await only pauses inside the async function');
This line runs first – await only pauses inside the async function Aarti: last order #1042 (₹1800)

try/catch/finally से errors

JavaScript
const wait = (ms) => new Promise(r => setTimeout(r, ms));
async function payWithUpi(amount) {
  await wait(50);
  if (amount > 10000) throw new Error('UPI limit exceeded for this demo');
  return `₹${amount} paid via UPI ✅`;
}

async function checkout(amount) {
  console.log('⏳ Processing…');
  try {
    const receipt = await payWithUpi(amount);
    console.log(receipt);
  } catch (err) {
    console.log('❌ Payment failed:', err.message);
  } finally {
    console.log('Spinner hidden');
  }
}
(async () => { await checkout(1800); await checkout(25000); })();
⏳ Processing… ₹1800 paid via UPI ✅ Spinner hidden ⏳ Processing… ❌ Payment failed: UPI limit exceeded for this demo Spinner hidden
💡 एक के बाद एक बनाम साथ-साथ

लगातार दो awaits एक के बाद एक चलते हैं। अगर requests एक-दूसरे पर निर्भर नहीं, तो साथ शुरू करें: const [menu, offers] = await Promise.all([getMenu(), getOffers()]); – अक्सर दोगुना तेज़।

fetch: आपका पहला API call

HTML + JavaScript
<button id="load">Load menu from the API</button>
<pre id="out" style="max-height:220px;overflow:auto;background:#111827;color:#a7f3d0;padding:10px;border-radius:8px">Click the button…</pre>

<script>
const API = 'https://codingeasily.in/api/sweets/';

document.querySelector('#load').addEventListener('click', async () => {
  const out = document.querySelector('#out');
  out.textContent = 'Loading…';
  try {
    const response = await fetch(API);                  // 1. send the request
    if (!response.ok) throw new Error('HTTP ' + response.status);   // 2. check the status!
    const products = await response.json();              // 3. read the JSON body
    out.textContent = `Status ${response.status} · ${products.length} products\n\n` +
      products.map(p => `${p.id}. ${p.name.padEnd(18)} ₹${p.price}/${p.unit}  stock ${p.stock}`).join('\n');
  } catch (err) {
    out.textContent = 'Could not load the menu: ' + err.message;
  }
});
</script>
▶  A real HTTP request to the course API
StepCodeक्यों
भेजेंconst res = await fetch(url)Headers आने पर resolve
जाँचेंif (!res.ok) throw …fetch 404/500 पर reject नहीं करता – सिर्फ़ network failure पर
पढ़ेंawait res.json() / res.text()Body अलग से पढ़ी जाती है, वह भी async
संभालेंसब के चारों ओर try/catchOffline, timeouts, ख़राब JSON, server errors
StatusमतलबUser को दिखाएँ
200 OK / 201 CreatedसफलData / “Order placed”
400 Bad Request / 422ग़लत inputField-level errors
401 / 403Login नहीं / अनुमति नहींLogin prompt
404 Not Foundग़लत URL या item नहीं“Product not found”
429 Too Many RequestsRate limited“रुककर दोबारा कोशिश करें”
500 / 502 / 503Server समस्या“कुछ गड़बड़ हुई, फिर कोशिश करें” + retry button

Loading, empty, error और success states

HTML + JavaScript
<style>
.grid { display: grid; grid-template-columns: repeat(auto-fill, minmax(150px, 1fr)); gap: 12px; margin-top: 10px; }
.card { border: 1px solid #e5e7eb; border-radius: 12px; overflow: hidden; background: #fff; }
.card img { width: 100%; aspect-ratio: 4 / 3; object-fit: cover; display: block; background: #f3f4f6; }
.card div { padding: 8px 10px; font-size: .9rem; }
.muted { color: #6b7280; }
.error { background: #fee2e2; color: #7f1d1d; padding: 10px; border-radius: 8px; }
.skeleton { height: 170px; border-radius: 12px; background: linear-gradient(90deg, #eee 25%, #f6f6f6 50%, #eee 75%); background-size: 200% 100%; animation: sh 1.2s linear infinite; }
@keyframes sh { to { background-position: -200% 0; } }
</style>

<input id="q" placeholder="Search (try kaju, box, xyz)" aria-label="Search">
<select id="cat" aria-label="Category"><option value="">All</option><option value="milk">Milk</option><option value="dry">Dry</option><option value="box">Gift boxes</option></select>
<label><input type="checkbox" id="slow"> Slow network</label>
<label><input type="checkbox" id="fail"> Server error</label>
<div id="view" aria-live="polite"></div>

<script>
const API = 'https://codingeasily.in/api/sweets/';
const view = document.querySelector('#view');

function showLoading() {
  view.innerHTML = '<div class="grid">' + '<div class="skeleton"></div>'.repeat(4) + '</div>';
}
function showError(message) {
  view.innerHTML = '';
  const box = document.createElement('div');
  box.className = 'error';
  box.textContent = '⚠️ ' + message + ' ';
  const retry = document.createElement('button');
  retry.textContent = 'Try again';
  retry.addEventListener('click', load);
  box.append(retry);
  view.append(box);
}
function showProducts(products) {
  if (products.length === 0) { view.innerHTML = '<p class="muted">No sweets match your search 🙁</p>'; return; }
  const grid = document.createElement('div');
  grid.className = 'grid';
  for (const p of products) {
    const card = document.createElement('article');
    card.className = 'card';
    card.innerHTML = '<img alt=""><div><b></b><br><span class="muted"></span></div>';
    card.querySelector('img').src = p.image;
    card.querySelector('b').textContent = p.name;
    card.querySelector('.muted').textContent = p.stock > 0 ? `₹${p.price}/${p.unit}` : 'Sold out';
    grid.append(card);
  }
  view.replaceChildren(grid);
}

async function load() {
  const params = new URLSearchParams();                       // builds ?q=kaju&category=dry safely
  const q = document.querySelector('#q').value.trim();
  const cat = document.querySelector('#cat').value;
  if (q) params.set('q', q);
  if (cat) params.set('category', cat);
  if (document.querySelector('#slow').checked) params.set('delay', 1500);
  if (document.querySelector('#fail').checked) params.set('fail', 1);

  showLoading();
  try {
    const res = await fetch(`${API}?${params}`);
    if (!res.ok) throw new Error(`The server had a problem (HTTP ${res.status}).`);
    showProducts(await res.json());
  } catch (err) {
    showError(err.message.startsWith('The server') ? err.message : 'You seem to be offline.');
  }
}
document.querySelectorAll('#q, #cat, #slow, #fail').forEach(el => el.addEventListener('change', load));
document.querySelector('#q').addEventListener('keyup', e => { if (e.key === 'Enter') load(); });
load();
</script>
▶  Tick “Slow network” or “Server error” and change the category to see every state
🧠 हर data screen को चार states चाहिए

Loading (skeletons), empty (“no results”), error (retry button के साथ) और success। ज़्यादातर beginner apps सिर्फ़ success बनाते हैं – फिर धीमे 4G पर ख़ाली screen दिखाते हैं। Interviewers और users फ़र्क देखते हैं।

Data भेजना: order POST करना

HTML + JavaScript
<form id="order">
  <input name="name" placeholder="Name" value="Aarti">
  <input name="phone" placeholder="Mobile" value="98290">
  <button>Place order (2 kg Kaju Katli)</button>
</form>
<pre id="res" style="background:#f8fafc;padding:10px;border-radius:8px"></pre>

<script>
const API = 'https://codingeasily.in/api/sweets/';
document.querySelector('#order').addEventListener('submit', async (e) => {
  e.preventDefault();
  const btn = e.currentTarget.querySelector('button');
  const out = document.querySelector('#res');
  const form = Object.fromEntries(new FormData(e.currentTarget));
  btn.disabled = true;                                   // prevent double orders
  out.textContent = 'Sending…';
  try {
    const res = await fetch(API, {
      method: 'POST',
      headers: { 'Content-Type': 'application/json' },
      body: JSON.stringify({ ...form, items: [{ id: 1, qty: 2 }] }),
    });
    const data = await res.json();
    if (res.status === 422) {                            // server-side validation errors
      out.textContent = '⚠️ ' + data.error + '\n' + Object.entries(data.fields).map(([f, m]) => `• ${f}: ${m}`).join('\n');
    } else if (!res.ok) {
      throw new Error('HTTP ' + res.status);
    } else {
      out.textContent = `✅ ${data.message}\nOrder ${data.orderId} · total ₹${data.total} (delivery ₹${data.delivery})`;
    }
  } catch (err) {
    out.textContent = '❌ Could not send the order: ' + err.message;
  } finally {
    btn.disabled = false;
  }
});
</script>
▶  Submit with the short number (422 errors), then fix it to 9829012345 (201 Created)

AbortController से timeouts और cancel

JavaScript – a reusable fetchJSON helper
async function fetchJSON(url, { timeout = 8000, ...options } = {}) {
  const controller = new AbortController();
  const timer = setTimeout(() => controller.abort(), timeout);
  try {
    const res = await fetch(url, { ...options, signal: controller.signal });
    const data = await res.json().catch(() => null);          // body may be empty
    if (!res.ok) {
      const error = new Error(data?.error || `HTTP ${res.status}`);
      error.status = res.status;
      error.data = data;
      throw error;
    }
    return data;
  } catch (err) {
    if (err.name === 'AbortError') throw new Error('The server took too long. Please try again.');
    throw err;
  } finally {
    clearTimeout(timer);
  }
}

// usage
const products = await fetchJSON('https://codingeasily.in/api/sweets/?category=dry', { timeout: 5000 });
⚠️ CORS – “blocked by CORS policy”

Browsers page को दूसरे domain के responses तभी पढ़ने देते हैं जब वह server Access-Control-Allow-Origin header से अनुमति दे। हमारा practice API यह भेजता है, इसलिए किसी भी page से चलता है। किसी दूसरे API में CORS error दिखे तो उसे server पर ठीक करना होगा (या अपने backend से बुलाएँ) – front-end code में नहीं।

🏅 आज के Job Skills

✔ await और try/catch के साथ async functions✔ fetch से APIs बुलाना और response.ok जाँचना✔ Loading, empty, error और success states बनाना✔ JSON POST, 422 errors, timeouts और parallel requests संभालना

Practice tasks

🏋️ Practice – ख़ुद करें

Task 1: ?id=2 से एक product load करके नाम और price दिखाएँ; फिर ?id=99 आज़माकर 404 status से “Product not found” दिखाएँ।
Solution देखें
▶  Result
Task 2: Promise.all से milk sweets और gift boxes साथ-साथ load करके दोनों की गिनती print करें।
Task 3: AbortController से product loader में 3-second timeout जोड़ें और ?delay=3000 से test करें।

Quick quiz

🧠 Quick Quiz – ख़ुद को जाँचें

1. Async function हमेशा लौटाता है…
Value लौटाएँ तब भी।
2. क्या fetch HTTP 500 पर reject करता है?
सिर्फ़ network failures।
3. JSON body पढ़ें…
वह भी async।
4. POST में JSON भेजें:
Stringify।
5. धीमी request रद्द करें:
controller.abort()।

Interview corner

💼 Interview Corner

fetch के साथ errors कैसे संभालें?

try/catch में रखें; network errors और aborts reject करते हैं, पर HTTP errors नहीं, इसलिए response.ok/status जाँचकर throw करें; messages के लिए error bodies parse करें; retry के साथ दोस्ताना states दिखाएँ; AbortController से timeouts; developers के लिए details log करें।

CORS क्या है?

Cross-Origin Resource Sharing: browser का security नियम जो page को दूसरे origin के responses पढ़ने से रोकता है जब तक server Access-Control-Allow-* headers से अनुमति न दे। JSON POST जैसी non-simple requests के लिए preflight OPTIONS requests भेजी जाती हैं।

सारांश

  • async/await = पठनीय promises; try/catch/finally में रखें।
  • fetch → res.ok जाँचें → await res.json()।
  • हमेशा loading, empty, error (+ retry) और success states बनाएँ।
  • Headers के साथ JSON POST; 422 field errors संभालें; timeouts के लिए AbortController।
➡️ आगे

Day 21: modules, npm और modern tooling – code को files में बाँटें और असली teams की तरह Vite इस्तेमाल करें।

अक्सर पूछे जाने वाले प्रश्न (FAQ)

क्या practice API अपने projects में इस्तेमाल कर सकता हूँ?
हाँ, सीखने के लिए। यह sample data लौटाता है, orders कभी save नहीं करता और बदल सकता है। असली दुकान के लिए अपना backend चाहिए (जैसे PHP/MySQL या Node)।
fetch या axios?
fetch built-in है और ज़्यादातर apps के लिए काफ़ी, ख़ासकर fetchJSON जैसे छोटे helper के साथ। axios सुविधाएँ (interceptors, अपने-आप JSON) जोड़ता है और पुराने projects में आम है।
← JavaScript (30 Days)
🔗

Share this topic with a friend

यह topic किसी दोस्त को भेजें

Found it useful? Send it to a classmate learning the same thing.

अच्छा लगा? जो दोस्त यही सीख रहा है, उसे भेज दीजिए।

अगला topicदिन 21: Modules, npm और Modern Tooling आपकी प्रगति: 20 / 30 (67%) · Lesson 21 / 30 आगे बढ़ें →

यह lesson कैसा लगा?

आपकी राय से हम content और बेहतर बनाते हैं।

अपना review और सुझाव लिखें (वैकल्पिक)

Review approve होने के बाद आपका नाम और शहर इसके साथ public दिख सकते हैं। Email या phone न लिखें।

▶ CodingEasily on YouTube

Video से सीखें – आसान Hindi में

चुनी हुई video: RDBMS भाग 3 – Class XI Commerce IT

▶ Channel subscribe करें