← Back to JavaScript Course | Chapter 4: Modern JS, Async & DOM | Lesson 23 of 26

JS एसिंक कॉलबैक्स

Promises और async/await के मौजूद होने से पहले, asynchronous JavaScript पूरी तरह callback functions पर निर्भर था -- एक ऐसा function जो argument के रूप में पास किया जाता है, और किसी operation के पूरा होने पर बाद में invoke होता है। पुराने code को पढ़ने के लिए और यह समझने के लिए कि Promises ठीक-ठीक किस समस्या को हल करने के लिए बनाए गए थे, callbacks को समझना अब भी ज़रूरी है।
Syntax
javascript
function functionName(callback) {
  // async work
  callback(result);
}

functionName(function(result) {
  // use result
});

Callback क्या है

एक callback बस एक regular function है जो किसी दूसरे function को argument के रूप में पास किया जाता है -- receiving function उसे बाद में किसी point पर वापस कॉल करता है, अक्सर किसी asynchronous operation (जैसे कोई timer या network request) के खत्म होने पर।

Note: याद रखें कि एक callback एक reference के रूप में पास किया जाता है (सिर्फ function का नाम, बिना parentheses) -- parentheses जोड़ना उसे बाद में कॉल किए जाने के लिए सौंपने के बजाय तुरंत कॉल कर देता है।
Warning: callback argument के रूप में myFunction के बजाय myFunction() पास करना myFunction को तुरंत execute कर देता है और callback के रूप में उसकी RETURN VALUE पास करता है, function को खुद नहीं।

उदाहरण: What a Callback Is

javascript
// Define the function `greet` taking `name`, `callback`
// Define the function `greet` taking `name`, `callback`
function greet(name, callback) {
  // Call `callback(`Hello, ${name}`)`
  // Call `callback(`Hello, ${name}`)`
  callback(`Hello, ${name}`);
}
// Call `greet("Sam", (message) => console.log(message))`
// Call `greet("Sam", (message) => console.log(message))`
greet("Sam", (message) => console.log(message));

Asynchronous Operations के साथ Callbacks

callback का classic इस्तेमाल इसे किसी ऐसी चीज़ के साथ जोड़ना है जिसमें समय लगे -- setTimeout(callback, delay) delay बीतने के बाद callback को कॉल करता है, और पुराने AJAX APIs किसी network response के आने पर code चलाने के लिए callbacks इस्तेमाल करते थे, क्योंकि "बाद में" होने वाली किसी चीज़ पर react करने का कोई और तरीका नहीं था।

Note: याद रखें कि किसी async callback इस्तेमाल करने वाली call के ठीक बाद का code callback के खुद fire होने से पहले चलता है -- callback का schedule होना बाकी script को नहीं रोकता।
Warning: एक callback-based async operation उसका synchronously "इंतज़ार" करने का कोई सीधा तरीका नहीं देता -- सारी dependent logic को callback के अंदर ही रहना होगा, या उससे trigger होना होगा।

उदाहरण: Callbacks with Asynchronous Operations

javascript
setTimeout(() => console.log("Runs later"), 500);
// Older AJAX used callbacks similarly, run once a response arrives

Error-First Callback Convention

एक व्यापक रूप से अपनाया गया convention, खासतौर पर Node.js-style code में, "error-first" callback है: callback(error, result), जहाँ पहला argument या तो एक Error object है (अगर कुछ गलत हुआ) या null (अगर सफल रहा) -- उस पहले argument को जांचना callback-based code में failure संभालने का standard तरीका बन जाता है।

Note: किसी error-first callback के अंदर हमेशा पहले error argument जांचें, result argument को छूने से पहले, क्योंकि error होने पर result बेमानी होता है (या मौजूद ही नहीं होता)।
Warning: error check को छोड़ना और यह मान लेना कि हर callback invocation success को represent करता है, callback-based code में bugs का एक आम कारण है, क्योंकि इस तरह errors को चुपचाप नज़रअंदाज़ करना आसान है।

उदाहरण: The Error-First Callback Convention

javascript
// Define the function `loadData` taking `callback`
// Define the function `loadData` taking `callback`
function loadData(callback) {
  // Call `setTimeout(() => callback(null, { id: 1 }), 100)`
  // Call `setTimeout(() => callback(null, { id: 1 }), 100)`
  setTimeout(() => callback(null, { id: 1 }), 100);
}
loadData((error, result) => {
  if (error) console.log("Failed:", error);
  else console.log("Success:", result);
});

समस्या: Callback Hell

जब कई asynchronous steps क्रम में होने चाहिए, हर एक पिछले वाले के result पर निर्भर, तो callback-based code गहराई में और गहरा nest होता जाता है -- एक pattern जिसे आमतौर पर 'callback hell' या 'the pyramid of doom' कहा जाता है, जो और steps जुड़ने के साथ सच में पढ़ना, बदलना, और debug करना मुश्किल हो जाता है।

Note: गहराई से nested callbacks को इस संकेत के रूप में पहचानें कि Promises या async/await उसी logic को कहीं ज़्यादा readable तरीके से express करेंगे।
Warning: गहराई से nested callbacks में error handling खासतौर पर तकलीफदेह हो जाती है, क्योंकि हर level को आमतौर पर अपना अलग error check चाहिए होता है, जो nesting के हर level पर boilerplate को कई गुना बढ़ा देता है।

उदाहरण: The Problem: Callback Hell

javascript
function step1(cb) { setTimeout(() => cb(1), 10); }
function step2(a, cb) { setTimeout(() => cb(a + 1), 10); }
function step3(b, cb) { setTimeout(() => cb(b + 1), 10); }
step1((a) => {
  step2(a, (b) => {
    step3(b, (c) => console.log("Deeply nested result:", c)); // callback hell
  });
});

Callbacks अभी भी इस्तेमाल में

ज़्यादातर sequential async logic के लिए Promises और async/await preferred होने के बावजूद, साधारण callbacks कुछ patterns के लिए आम और उपयुक्त बने हुए हैं -- event listeners (addEventListener), array iteration methods (forEach, map), और कोई भी 'हर बार X होने पर इसे चलाओ' वाला scenario जो असल में किसी single eventual result के बारे में नहीं है।

Note: यह पहचानें कि callbacks "deprecated" नहीं हैं -- वे repeated या event-driven invocations के लिए सही tool बने हुए हैं, जबकि Promises किसी single eventual async result के लिए बेहतर फिट बैठते हैं।
Warning: किसी event listener (जो कई बार fire हो सकता है) को किसी Promise-based pattern (जो एक single resolution के लिए designed है) में जबरदस्ती फिट करने की कोशिश करना आमतौर पर एक कमज़ोर fit है -- वहाँ callbacks ही स्वाभाविक विकल्प बने रहते हैं।

उदाहरण: Callbacks Still in Use Today

javascript
document.addEventListener("click", () => console.log("Clicked")); // still a normal, appropriate callback use
[1, 2, 3].forEach(n => console.log(n)); // another normal callback use
Live Example
Related Topics
{# common_mistakes/chapter_summary/browser_support: on Hindi pages the view already swaps in the hi_ translation fields (or blanks these out if untranslated), so this renders correctly for both languages without a lang_code check here. #}
आम गलतियां
  1. dependent async steps की एक sequence के लिए callback के अंदर callback के अंदर callback nest करना, deeply indented, follow करने में मुश्किल code produce करते हुए जिसे अक्सर 'callback hell' कहा जाता है।
  2. error-first callback convention inconsistently follow करना, result argument इस्तेमाल करने से पहले error argument check करना भूल जाना।
  3. किसी callback function को reference pass करने के बजाय उसे तुरंत (parentheses के साथ) कॉल करना, उसे बाद के लिए schedule करने के बजाय उसे तुरंत execute करते हुए।
चैप्टर सारांश
  • एक callback बस एक ऐसा function है जो किसी दूसरे function को argument की तरह pass किया जाता है, किसी operation के पूरा होने पर बाद में invoke किया जाने के लिए।
  • error-first convention (callback(error, result)) एक common pattern है जहाँ पहला argument या तो एक error object होता है या null।
  • sequential async steps के लिए deeply nested callbacks एक हार्ड-टू-रीड "callback hell" produce करते हैं, जिसे solve करने के लिए Promises और async/await design किए गए थे।
ब्राउज़र सपोर्ट

callback pattern खुद एक basic JavaScript language feature है, जिसे language के बनने से support मिला है, और यह हर environment में काम करता है।

Login to run this code

C/C++/Java/PHP execution requires a free account. Your code is saved — you'll land right back in the editor after logging in.