असिंक्रोनस जावास्क्रिप्ट

कुछ चीजें तुरंत होती हैं: दो नंबरों को जोड़ना, एक वेरिएबल पढ़ना, पेज पर टेक्स्ट बदलना। दूसरी चीजों को समय लगता है। एक टाइमर तीन सेकंड के लिए काउंटडाउन करता है। एक सर्वर को भेजा गया अनुरोध नेटवर्क के पार जाता है और कुछ समय बाद वापस आता है। अगर जावास्क्रिप्ट रुकता और इनमें से हर एक के लिए प्रतीक्षा करता, तो पूरा पेज फ्रीज हो जाता: कोई क्लिक नहीं, कोई स्क्रोलिंग नहीं, कुछ भी नहीं, जब तक कि धीमी चीज खत्म न हो जाए। यह काम नहीं करता। यह अध्याय इस बारे में है कि जावास्क्रिप्ट कैसे कुछ धीमा शुरू करता है, पेज को प्रतिक्रियाशील रखता है, और नतीजा तैयार होने पर उसे संभालने के लिए वापस आता है।
असिंक्रोनस क्यों
अधिकांश जावास्क्रिप्ट ऊपर से नीचे तक चलता है, एक लाइन अगली को शुरू करने से पहले खत्म होती है। तेज़ काम के लिए यह ठीक है। लेकिन कुछ कार्यों को वास्तविक समय लगता है, और जावास्क्रिप्ट उनके लिए बैठकर प्रतीक्षा नहीं करता। यह धीमा कार्य शुरू करता है, अगली लाइन पर जाता है, और जब यह किया जाता है तो धीमी चीज पर वापस आता है। यही असिंक्रोनस का मतलब है: क्रम में नहीं होना, अभी नहीं, बल्कि बाद में, जब नतीजा तैयार हो।
सबसे सरल उदाहरण एक टाइमर है। setTimeout देरी के बाद कोड का एक टुकड़ा चलाता है:
console.log("Start");
setTimeout(() => {
console.log("3 seconds later");
}, 3000);
console.log("End");
// Start
// End
// 3 seconds laterऑर्डर पर ध्यान दें। "End" "3 seconds later" से पहले प्रिंट होता है, भले ही यह कोड में setTimeout के बाद आता है। जावास्क्रिप्ट उस लाइन पर तीन सेकंड तक प्रतीक्षा नहीं करता। इसने टाइमर सेट किया, आगे बढ़ा, और समय समाप्त होने पर विलंबित कोड चलाया।
"End" कोड में टाइमर के पहले भी setTimeout संदेश से पहले प्रिंट होता है। Promises
setTimeout एक delay के लिए ठीक है, लेकिन अधिकांश async काम एक value produce करता है जिसकी आप परवाह करते हैं: वह डेटा जो आपने मांगा था, या एक error अगर यह गलत हुआ। इसके लिए, जावास्क्रिप्ट एक promise का उपयोग करता है। एक promise एक value है जो अभी तैयार नहीं है, इसके लिए एक जगह सुरक्षित रखते हुए। यह एक receipt की तरह है: आपके पास खाना नहीं है, लेकिन आपके पास कुछ ऐसा है जो खाने में बदल जाएगा।
एक promise दो तरीकों में से एक समाप्त होता है। यह resolve होता है एक value के साथ जब काम सफल होता है, या reject होता है एक error के साथ जब यह विफल होता है। आप प्रत्येक case में .then() और .catch() के साथ बताते हैं कि क्या करना है:
loadUser()
.then((user) => {
console.log(`Loaded ${user.name}`);
})
.catch((error) => {
console.log("Something went wrong");
});.then() चलता है जब promise resolve होता है, और यह value प्राप्त करता है। .catch() चलता है अगर यह reject होता है, और यह error प्राप्त करता है। उनके अंदर का कोड बाद में चलता है, एक बार नतीजा आने पर।
.then() के साथ value के लिए और .catch() के साथ error के लिए बताते हैं कि क्या करना है, और दोनों बाद में चलते हैं एक बार नतीजा आने पर। async / await
Promise chains काम करते हैं, लेकिन एक cleaner तरीका है उन्हें लिखने का जो लगभग सामान्य top-to-bottom कोड की तरह पढ़ता है। यह दो keywords का उपयोग करता है, async और await।
आप एक फंक्शन को async चिह्नित करते हैं, और इसके अंदर आप एक promise को await कर सकते हैं। await फंक्शन को pause करता है जब तक promise resolve नहीं हो जाता, फिर आपको value सीधे देता है, कोई .then() की जरूरत नहीं:
async function showUser() {
const user = await loadUser();
console.log(`Loaded ${user.name}`);
}उसे top से bottom तक पढ़ें: user को get करो, फिर name को log करो। await लाइन loadUser() को खत्म होने तक प्रतीक्षा करती है और आपको user देती है। फंक्शन वहाँ pause होता है, लेकिन बाकी पेज चलता रहता है, तो कुछ भी freeze नहीं होता।
Errors को handle करने के लिए, await को try और catch में wrap करें:
async function showUser() {
try {
const user = await loadUser();
console.log(`Loaded ${user.name}`);
} catch (error) {
console.log("Could not load the user");
}
}अगर promise विफल होता है, कोड catch block में जाता है बजाय crash करने के।
async चिह्नित करें और आप इसके अंदर एक promise को await कर सकते हैं। await उस फंक्शन को तब तक pause करता है जब तक promise resolve न हो जाए और सीधे value को आपको देता है, तो कोड top से bottom तक कोई .then() के साथ नहीं पढ़ता। इसे try और catch में wrap करें failures को handle करने के लिए, और पेज चलता रहता है जबकि फंक्शन प्रतीक्षा करता है। डेटा को फेच करना
सबसे आम async task जो आप लिखेंगे वह एक सर्वर से डेटा लोड करना है। ब्राउज़र इसके लिए आपको fetch देता है। आप इसे एक URL pass करते हैं, और यह response के लिए एक promise return करता है:
async function loadUsers() {
const response = await fetch("https://api.example.com/users");
const users = await response.json();
console.log(users);
}दो await हैं, और यह लोगों को पहली बार आश्चर्यचकित करता है। पहला server के respond करने के लिए प्रतीक्षा करता है। दूसरा उस response का body पढ़ता है और इसे .json() के साथ जावास्क्रिप्ट डेटा में बदलता है, जो अपने आप में async है। तो fetching दो steps हैं: response को get करो, फिर उसे read करो।
Servers एक error के साथ भी respond कर सकते हैं, जैसे "not found"। fetch अपने आप पर उसे एक विफलता के रूप में नहीं treat करता, तो आप response.ok को अपने आप check करते हैं:
async function loadUsers() {
const response = await fetch("https://api.example.com/users");
if (!response.ok) {
console.log("Request failed");
return;
}
const users = await response.json();
console.log(users);
}fetch(url) सर्वर के response के लिए एक promise return करता है, और डेटा लोड करना दो steps हैं: response के लिए await fetch(...), फिर await response.json() को डेटा को इसके से read करने के लिए। एक सर्वर error जैसे "not found" अपने आप fail नहीं होता, तो body को read करने से पहले response.ok को check करें। दोनों steps await का उपयोग करते हैं क्योंकि दोनों को समय लगता है। Event loop और parallel में काम चलाना
अब तक सब कुछ एक theme रखता है: जावास्क्रिप्ट धीमा काम शुरू करता है, आगे बढ़ता है, और बाद में इसमें वापस आता है। यह खंड उसके पीछे का तंत्र है, साथ ही कई async tasks को अच्छी तरह से चलाने के लिए patterns हैं।
यहाँ एक picture है कि जावास्क्रिप्ट कैसे async काम के ट्रैक को रखता है। आपका running कोड call stack पर बैठता है, अभी जो execute हो रहा है उसकी list है। जब आप setTimeout को call करते हैं, timer को ब्राउज़र को hand off किया जाता है countdown करने के लिए, तो यह stack पर नहीं है कुछ भी block करते हुए। जब timer खत्म हो जाता है, इसका callback एक task queue में जाता है, code की एक waiting line जो चलने के लिए तैयार है।
event loop वह हिस्सा है जो उन्हें connect करता है। इसका एक rule है: पहले call stack पर सब कुछ चलाएं, और केवल जब stack empty हो तो queue से अगला task pull करें। यही कारण है कि setTimeout(fn, 0) अभी भी आपके दूसरे कोड के बाद चलता है, एक zero delay के साथ भी। callback को queue में wait करना होता है current code के खत्म होने तक:
console.log("first");
setTimeout(() => console.log("third"), 0);
console.log("second");
// first
// second
// third0 का delay मतलब "right now" नहीं है। यह मतलब है "जैसे ही current code खत्म हो"।
setTimeout(fn, 0) अभी भी आपने बाकी कोड के बाद चलता है। 0 की delay मतलब है "right now" नहीं, बल्कि "जैसे ही current code खत्म हो"। Async यहाँ से कहाँ जाता है
Async जावास्क्रिप्ट का वह हिस्सा है जो एक पेज को जीवंत रखता है जबकि धीमा काम background में होता है। shape हमेशा एक जैसा है: कुछ ऐसा शुरू करो जो समय लेता है, अपने बाकी कोड को चलने दो, और नतीजे को handle करो जब यह आता है। Promises उस नतीजे को एक value देता है जिसे आप pass around कर सकते हैं, async/await आपको plain top-to-bottom कोड में इसे लिखने देता है, और fetch है जहाँ आप सब का उपयोग सबसे ज्यादा करेंगे, एक सर्वर से डेटा लोड करते हुए।
यहाँ से, async language के उन हिस्सों से connects करता है जो बाहरी दुनिया को react करते हैं। आप fetched डेटा को the DOM के माध्यम से पेज में wire करेंगे, और आप async काम को kick off करेंगे जवाब में जो लोग पेज पर करते हैं, जो events है। नतीजे जो आप वापस पाते हैं वह लगभग हमेशा objects हैं, तो उन्हें read और reshape करना अगली skill है जो यहाँ सब के साथ pairs करती है।

