कंट्रोल फ़्लो

कंट्रोल फ़्लो वह क्रम है जिसमें 'JavaScript इंटरप्रेटर' स्टेटमेंट दिखाता है. अगर किसी स्क्रिप्ट में ऐसे स्टेटमेंट शामिल नहीं हैं जिनसे फ़्लो में बदलाव होता है, तो उसे शुरू से आखिर तक, एक-एक करके चलाया जाता है. कंट्रोल स्ट्रक्चर का इस्तेमाल यह तय करने के लिए किया जाता है कि स्टेटमेंट के किसी सेट को, तय किए गए मापदंड के आधार पर लागू किया जाए या नहीं, स्टेटमेंट के सेट को बार-बार लागू किया जाए या नहीं या स्टेटमेंट के क्रम को बाधित किया जाए.

कंडिशनल स्टेटमेंट

'शर्त के साथ स्टेटमेंट' यह तय करते हैं कि कोड को एक या एक से ज़्यादा शर्तों के हिसाब से लागू किया जाना चाहिए या नहीं. कंडीशनल स्टेटमेंट, उसमें शामिल कोड को तब लागू करता है, जब उससे जुड़ी शर्त (या शर्तों के सेट) का आकलन true होता है. ऐसा न करने पर, कोड छोड़ दिया जाता है.

ifelse

if स्टेटमेंट, मेल खाने वाले ब्रैकेट के अंदर शर्त की जांच करता है. अगर ब्रैकेट के अंदर की शर्त का आकलन true होता है, तो मेल खाने वाले ब्रैकेट के बाद वाला स्टेटमेंट या ब्लॉक करें स्टेटमेंट लागू हो जाता है:

if ( true ) console.log( "True." );
> "True."

if ( true ) {
    const myString = "True.";
    console.log( myString );
}
> "True."

अगर ब्रैकेट के अंदर दी गई शर्त का आकलन false होता है, तो इसके बाद वाले स्टेटमेंट को अनदेखा कर दिया जाता है:

if ( false ) console.log( "True." );

if स्टेटमेंट के ठीक बाद मौजूद else कीवर्ड और शर्त के साथ एक्ज़ीक्यूट किया गया स्टेटमेंट, यह बताता है कि अगर if की शर्त का आकलन false के तौर पर किया जाता है, तो यह स्टेटमेंट लागू होगा:

if ( false ) console.log( "True." )''
else console.log( "False" );
> "False."

कई if स्टेटमेंट को एक साथ चेन करने के लिए, else किसी दूसरे if स्टेटमेंट के बाद शर्त के साथ लागू किया गया स्टेटमेंट बनाया जा सकता है:

const myCondition = 2;
if ( myCondition === 5 ) console.log( "Five." );
else if ( myCondition === 2 ) console.log( "Two." );

हमारा सुझाव है कि कॉन्टेंट को बेहतर ढंग से पढ़ने लायक बनाने के लिए, शर्तों के मुताबिक बने ब्लॉक स्टेटमेंट सिंटैक्स का इस्तेमाल करें. हालांकि, else if क्लॉज़ अक्सर इसका अपवाद होते हैं:

if ( myCondition === 5 ) {
    console.log( "Five." );
} else if ( myCondition === 3 ) {
    console.log( "Three" );
} else {
    console.log( "Neither five nor three." );
}
> "Neither five nor three."

टर्नरी ऑपरेटर

if शर्त के साथ स्टेटमेंट को लागू करता है. टर्नरी ऑपरेटर (ज़्यादा सटीक तरीके से, इसे टर्नरी कंडीशनल ऑपरेटर नहीं कहा जाता है) का इस्तेमाल, किसी एक्सप्रेशन को शर्त के साथ एक्ज़ीक्यूट करने के लिए किया जाता है. जैसा कि नाम से ही साफ़ है, टर्नरी ऑपरेटर ही एक ऐसा JavaScript ऑपरेटर है जो तीन ऑपरैंड का इस्तेमाल करता है:

  • ऐसी शर्त जिसका आकलन करना है और उसके बाद सवाल का निशान (?) आता है.
  • वह एक्सप्रेशन जिसे लागू करना है. अगर शर्त से true का आकलन होता है, तो उसके बाद कोलन (:) आता है.
  • अगर शर्त का आकलन false पर होता है, तो उसे लागू किया जाने वाला एक्सप्रेशन.

इसका इस्तेमाल अक्सर शर्त के साथ सेट करने या वैल्यू को पास करने के लिए किया जाता है:

const myFirstResult  = true  ? "First value." : "Second value.";
const mySecondResult = false ? "First value." : "Second value.";

myFirstResult;
> "First value."

mySecondResult;
> "Second value."

switchcase

एक या ज़्यादा case कीवर्ड का इस्तेमाल करके तय किए गए संभावित मानों की सूची से किसी व्यंजक के मान की तुलना करने के लिए switch कथन का इस्तेमाल करें. यह सिंटैक्स असामान्य है, क्योंकि यह JavaScript के डिज़ाइन से जुड़े सबसे पुराने फ़ैसलों से आता है. switch...case सिंटैक्स में switch कीवर्ड का इस्तेमाल होता है. इसके बाद, एक एक्सप्रेशन का इस्तेमाल किया जाता है, जिसे ब्रैकेट में रैप किया जाना है. इसके बाद, कर्ली ब्रेसेस का एक मिलता-जुलता जोड़ा होता है. switch के मुख्य हिस्से में आम तौर पर एक या उससे ज़्यादा case कीवर्ड हो सकते हैं. इसके बाद, कोई एक्सप्रेशन या वैल्यू होती है और उसके बाद कोलन (:) होता है.

जब अनुवादक, switch कीवर्ड के बाद ब्रैकेट में दिए गए एक्सप्रेशन से मैच होने वाली वैल्यू के साथ case पर पहुंचता है, तो वह उस case क्लॉज़ के मुताबिक बने किसी भी स्टेटमेंट को एक्ज़ीक्यूट करता है:

switch ( 2 + 2 === 4 ) {
  case false:
    console.log( "False." );
  case true:
    console.log( "True." );
}
> "True."

मिलते-जुलते case के बाद वाले सभी स्टेटमेंट लागू होते हैं, भले ही वे ब्लॉक करें स्टेटमेंट में हों.

switch ( 2 + 2 === 4 ) {
    case false:
    console.log( "False." );
  case true:
    let myVariable = "True.";
    console.log( myVariable );

}
> "True."

switch…case का इस्तेमाल करने के दौरान एक गलती यह है कि मैच मिलने के बाद, JavaScript का अनुवादक, मेल खाने वाले case के बाद वाले किसी भी स्टेटमेंट को एक्ज़ीक्यूट कर देता है. भले ही, वे अन्य case क्लॉज़ में हों. इसे अगले case पर "फ़ॉलिंग थ्रू" कहा जाता है:

switch ( 2 + 2 === 7 ) {
    case false:
    console.log( "False." );
  case true:
    console.log( "True." );
}
> "False."
> "True."

फ़ॉल-थ्रू से बचने के लिए, हर केस को break कीवर्ड से खत्म करें. इससे switch मुख्य भाग का आकलन तुरंत बंद हो जाता है:

switch ( 2 + 2 === 7 ) {
    case false:
    console.log( "False." );
    break;
  case true:
    console.log( "True." );
    break;
}
> "False."

अगर कोई भी case, कंडीशनल वैल्यू से मैच नहीं करता है, तो switch, default क्लॉज़ को तब चुनता है, जब:

switch ( 20 ) {
    case 5:
    console.log( "The value was five." );
    break;
  case 10:
    console.log( "The value was ten." );
    break;
  default:
    console.log( "The value was something unexpected." );
}
> "The value was something unexpected."

हालांकि, फ़ॉल-थ्रू default पर भी लागू होता है, जिससे अनचाहे नतीजे मिल सकते हैं. इसे ठीक करने के लिए, अपने default स्टेटमेंट के आखिर में break लिखें या इसे केस की सूची में आखिर में रखें.

switch ( 20 ) {
  default:
    console.log( "The value was something unexpected." );
  case 10:
    console.log( "The value was ten." );
    break;
  case 5:
    console.log( "The value was five." );
    break;
}
> The value was something unexpected.
> The value was ten.

case क्लॉज़ में एक से ज़्यादा स्टेटमेंट को ग्रुप करने के लिए, ब्लॉक करने की जानकारी की ज़रूरत नहीं होती. इसलिए, case और default क्लॉज़ अपने-आप लेक्सिकल स्कोप नहीं बनाते:

let myVariable;
switch ( true ) {
  case true:
    let myVariable = "True.";
    break;
  default:
    let myVariable = "False.";
    break;
}
> Uncaught SyntaxError: redeclaration of let myVariable

दायरा मैनेज करने के लिए, ब्लॉक स्टेटमेंट का इस्तेमाल करें:

let myVariable;
switch ( true ) {
  case true: {
    let myVariable = "True.";
    break;
  }
  default: {
    let myVariable = "False.";
    break;
  }
}

लूप और इटरेशन

लूप में, आपको स्टेटमेंट के सेट को तब तक दोहराने का विकल्प मिलता है, जब तक कोई शर्त पूरी होती है या शर्त पूरी होती है. खास नतीजा मिलने तक या अनुवाद करने वाला व्यक्ति फिर से इस्तेमाल किए जा सकने वाले डेटा स्ट्रक्चर (उदाहरण के लिए, किसी अरे, मैप या सेट का फ़ाइनल एलिमेंट, किसी ऑब्जेक्ट की आखिरी प्रॉपर्टी या स्ट्रिंग का आखिरी वर्ण) तक पहुंचने तक, निर्देशों के सेट को एक तय संख्या में एक्ज़ीक्यूट करने के लिए लूप का इस्तेमाल करें.

लूप, लूप बनाने के लिए इस्तेमाल किए गए सिंटैक्स के आधार पर स्टेटमेंट के एक सेट पर दोहराव करके उस स्क्रिप्ट के "टॉप टू बॉटम" फ़्लो में रुकावट डालता है. लूप खत्म होने के बाद, कार्रवाई उसी स्टेटमेंट के साथ जारी रहती है जो इसके बाद आता है. यहां दिए गए उदाहरण में बताया गया है कि इंटरप्रेटर के आगे बढ़ने से पहले, लूप के मुख्य हिस्से में मौजूद स्टेटमेंट को तीन बार चलाया जाता है:

let iterationCount = 0;
console.log( "Pre-loop." );
while( iterationCount < 3 ) {
  iterationCount++;
  console.log( "Loop iteration." );
}
console.log( "Continuing on." );
> "Pre-loop."
> "Loop iteration."
> "Loop iteration."
> "Loop iteration."
> "Continuing on."

अगर लूप के चलने के दौरान शर्तें पूरी नहीं होती हैं, तो लूप हमेशा के लिए जारी रहता है. ये इनफ़ाइनाइट लूप, प्रोग्रामिंग से जुड़ी एक आम गलतियां हैं. इनकी वजह से, मुख्य एक्ज़ीक्यूशन थ्रेड हमेशा के लिए रुक सकती है या ब्राउज़र टैब को क्रैश भी कर सकती है.

नीचे दिए गए उदाहरण में, बूलियन वैल्यू true तब तक काम करती है, जब तक true मौजूद रहता है. बूलियन वैल्यू को नहीं बदला जा सकता, इसलिए इससे इनफ़ाइनाइट लूप बन जाता है.

console.log( "Pre-loop." );
while( true ) {
console.log( "Loop iteration." );
}
> "Pre-loop."
> "Loop iteration."
> "Loop iteration."
> "Loop iteration."
> "Loop iteration."
> "Loop iteration."
…

अपने प्रोडक्शन कोड में अनंत लूप न डालें. अगर आपने डेवलपमेंट के दौरान गलती से एक नया खाता बना दिया है, तो आप उसमें चल रहे ब्राउज़र टैब को बंद करके, अपना कोड अपडेट करके, अपने कोड को अपडेट करके उसे ठीक कर सकते हैं, ताकि लूप अनगिनत न रहे. इसके बाद, पेज को फिर से खोलें.

while

while कीवर्ड का इस्तेमाल करके एक while लूप बनाया जाता है. इसके बाद, मेल खाने वाले ब्रैकेट की एक जोड़ी होती है, जिसमें आकलन की जाने वाली शर्त होती है. अगर तय की गई शर्त शुरू में true का आकलन करती है, तो उन ब्रैकेट के बाद वाला स्टेटमेंट (या ब्लॉक करें स्टेटमेंट) लागू हो जाता है. अगर नहीं, तो लूप कभी नहीं चलता. हर बार दोहराने के बाद, स्थिति का फिर से आकलन किया जाता है. अगर यह अब भी true है, तो लूप दोहराया जाता है.

let iterationCount = 0;
while( iterationCount < 3 ) {
  iterationCount++;
  console.log( `Loop ${ iterationCount }.` );
}
> "Loop 1."
> "Loop 2."

अगर अनुवादक को while लूप में continue स्टेटमेंट मिलता है, तो यह उस इटरेशन को रोक देता है, स्थिति का फिर से मूल्यांकन करता है, और हो सके तो लूप को जारी रखता है:

let iterationCount = 0;
while( iterationCount <= 5 ) {
  iterationCount++;
  if( iterationCount === 3 ) {
    continue;
  }
  console.log( `Loop ${ iterationCount }.` );
}
console.log( "Loop ended." );
> "Loop 1."
> "Loop 2."
> "Loop 4."
> "Loop 5."
> "Loop ended."

अगर अनुवादक को while लूप में break स्टेटमेंट दिखता है, तो इटरेशन रुक जाता है और स्थिति का फिर से आकलन नहीं किया जाता. इसलिए, अनुवादक को आगे बढ़ने दिया जाता है:

let iterationCount = 1;
while( iterationCount <= 5 ) {
  if( iterationCount === 3 ) {
    console.log(`Iteration skipped.``);`
    break;
  }
  console.log( `Loop ${ iterationCount }.` );
  iterationCount++;
}
console.log( "Loop ended." );
> "Loop 1."
> "Loop 2."
> "Iteration skipped.
> "Loop ended."

while का इस्तेमाल एक तय संख्या में फिर से करने के लिए किया जा सकता है, जैसा कि पिछले उदाहरण में दिखाया गया है. हालांकि, while के इस्तेमाल का सबसे आम उदाहरण, लूप की लंबाई वाला लूप है:

let randomize = () => Math.floor( Math.random() * 10 );
let randomNum = randomize();
while( randomNum !== 3 ){
  console.log( `The number is not ${ randomNum }.` );
  randomNum = randomize();
}
console.log( `The correct number, ${ randomNum }, was found.` );
> "The number is not 0."
> "The number is not 6."
> "The number is not 1."
> "The number is not 8."
> "The correct number, 3, was found."

dowhile

do...while, while लूप का एक वैरिएंट है. इसमें कंडिशनल इवैलुएशन, लूप के हर इटरेशन के आखिर में होता है. इसका मतलब है कि लूप के मुख्य हिस्से को हमेशा कम से कम एक बार चलाया जाता है.

do...while लूप बनाने के लिए, लूप के हर इटरेशन पर चलने के लिए, do कीवर्ड के बाद स्टेटमेंट (या ब्लॉक स्टेटमेंट) का इस्तेमाल करें. इस स्टेटमेंट के तुरंत बाद, while और मिलान किए गए ऐसे ब्रैकेट जोड़ें जिनमें वह शर्त शामिल है जिसकी जांच करनी है. जब यह शर्त true पर आकलन नहीं करती है, तो लूप खत्म हो जाता है.

let iterationCount = 1;
do {
  console.log( `Loop ${ iterationCount }.` );
  iterationCount++;
} while ( iterationCount < 3 );
> "Loop 1."
> "Loop 2."
> "Loop 3."

while लूप की तरह, do के इस्तेमाल का सबसे आम उदाहरण...while है, जिसकी लंबाई तय नहीं है:

let randomNum;
do {
  randomNum = ( () => Math.floor( Math.random() * 10 ) )();
  console.log( `Is the number ${ randomNum }?` );
} while ( randomNum !== 3 );
console.log( `Yes, ${ randomNum } was the correct number.` );
> "Is the number 9?"
> "Is the number 2?"
> "Is the number 8?"
> "Is the number 2?"
> "Is the number 3?"
> "Yes, 3 was the correct number."

for

तय संख्या पर दोहराने के लिए for लूप का इस्तेमाल करें. लेगसी कोडबेस में, इसका इस्तेमाल अक्सर किसी अरे में एलिमेंट को फिर से लागू करने के लिए किया जाता था.

for लूप बनाने के लिए, for कीवर्ड का इस्तेमाल करें. इसके बाद, ब्रैकेट का एक ऐसा सेट इस्तेमाल करें जो यहां दिए गए तीन एक्सप्रेशन को क्रम से स्वीकार करता हो और सेमीकोलन से अलग करता हो:

  1. लूप शुरू होने पर आकलन किया जाने वाला एक्सप्रेशन
  2. ऐसी शर्त जो तय करती है कि लूप जारी रखना चाहिए या नहीं
  3. हर लूप के नतीजे पर एक्ज़ीक्यूट किया जाने वाला व्यंजक

इन ब्रैकेट के बाद, लूप के दौरान एक्ज़ीक्यूट करने के लिए स्टेटमेंट (आम तौर पर एक ब्लॉक स्टेटमेंट) जोड़ें.

for( let i = 0; i < 3; i++ ) {
  console.log( "This loop will run three times.")
}

पहला एक्सप्रेशन ऐसे वैरिएबल को शुरू करता है जो काउंटर के तौर पर काम करता है. इस एक्सप्रेशन का आकलन, लूप की पहली कार्रवाई से पहले एक बार किया जाता है. किसी भी दूसरे वैरिएबल की तरह ही, let या अब तक var का इस्तेमाल करके, इस वैरिएबल को शुरू किया जा सकता है. इसका स्कोप, लूप का मुख्य हिस्सा होता है. इन वैरिएबल का कोई भी मान्य आइडेंटिफ़ायर हो सकता है. हालांकि, "दोहराव" या "इंडेक्स" के लिए इन्हें i कहा जाता है. ऐसा लगता है कि इन आइडेंटिफ़ायर के लिए पहले से तय किए गए सबसे सही तरीकों के हिसाब से, ऐसा नहीं किया जा सकता. लेकिन यह इतनी अच्छी तरह से स्थापित है कि दूसरे डेवलपर को एक नज़र में यह आसानी से समझ आ जाएगा. इंडेक्स किए गए कलेक्शन को इंडेक्स नहीं किया जाता. इसलिए, इन वैरिएबल की शुरुआती वैल्यू हमेशा 0 होती है.

लूप के दूसरे तरीकों की तरह, शर्त एक एक्सप्रेशन है, जिससे तय होता है कि लूप को लागू किया जाना चाहिए या नहीं. इसका इस्तेमाल आम तौर पर, इटरेशन काउंटर के लिए अपर बाउंड को सेट करने के लिए किया जाता है. अनुवादक, for लूप को पहली बार इस्तेमाल करने से पहले शर्त का आकलन करता है.अगर शुरुआत में शर्त का आकलन true नहीं होता है, तो लूप का मुख्य हिस्सा लागू नहीं होता.

आखिरी एक्सप्रेशन को लूप की हर इटरेशन के आखिर में एक्ज़ीक्यूट किया जाता है. आम तौर पर, इसका इस्तेमाल आइडेंटिफ़ायर को एक बढ़ाने के लिए किया जाता है.

आपको आम तौर पर, पुराने कोडबेस में अरे के ज़रिए दोहराए जाने वाले for लूप दिखेंगे. इन मामलों में, लूप को जारी रखने के लिए तय की गई शर्त, दोहराए जाने वाले अरे की लंबाई से कम या उसके बराबर इटरेशन काउंट है. इटरेशन की मौजूदा संख्या को ट्रैक करने के लिए इस्तेमाल किए जाने वाले वैरिएबल का इस्तेमाल, अरे में उस इंडेक्स से जुड़ी वैल्यू को खोजने के लिए किया जाता है. इससे अरे में मौजूद हर एलिमेंट को क्रम से कार्रवाई की जाती है:

var myArray = [ true, false, true ];
for( let i = 0; i <= myArray.length; i++ ) {
  console.log( myArray[ i ] );
}
> true
> false
> true

इटरेबल डेटा स्ट्रक्चर से छेड़छाड़ करने के लिए, यह तरीका ज़्यादा आधुनिक तरीकों के हिसाब से काम नहीं करता.

for [...] of [...]

किसी इटरेबल डेटा स्ट्रक्चर, जैसे कि अरे, सेट या मैप में स्टोर की गई वैल्यू पर फिर से लागू करने के लिए, for...of... लूप का इस्तेमाल करें.

एक for...of... लूप, for कीवर्ड का इस्तेमाल करता है. इसके बाद, वैरिएबल वाले ब्रैकेट के सेट का इस्तेमाल करता है. इसके बाद, of होता है. इसके बाद, डेटा स्ट्रक्चर को फिर से दोहराया जाता है. वैरिएबल के लिए यहां एलान किया जा सकता है. इसके लिए let, const या var का इस्तेमाल किया जा सकता है. यह मौजूदा स्कोप में पहले से एलान किए गए वैरिएबल, ऑब्जेक्ट प्रॉपर्टी या असाइनमेंट को नष्ट करने के उदाहरण हो सकता है. इसमें उस एलिमेंट की वैल्यू होती है जो लूप के मौजूदा इटरेशन के साथ मेल खाती है.

const myIterable = [ true, false, true ];
for( const myElement of myIterable ) {
  console.log( myElement );
}
> true
> false
> true

इस उदाहरण में, myElement के लिए const का इस्तेमाल करने से काम होता है. भले ही, myElement को लूप के हर इटरेशन में एक नई वैल्यू दी गई हो. इसकी वजह यह है कि let या const का एलान किए गए वैरिएबल, लूप में मौजूद ब्लॉक स्टेटमेंट के दायरे में होते हैं. वैरिएबल को हर इटरेशन की शुरुआत में शुरू किया जाता है और उसके आखिर में हटा दिया जाता है.

forin

किसी ऑब्जेक्ट की गिनने लायक प्रॉपर्टी पर फिर से लागू करने के लिए, for...in... लूप का इस्तेमाल करें. इसमें इनहेरिट की गई गिनने लायक प्रॉपर्टी भी शामिल हैं. for...of... लूप, एक for...in... लूप में for कीवर्ड का इस्तेमाल होता है, जिसमें ब्रैकेट का एक सेट होता है. इस वैरिएबल के बाद in कीवर्ड आता है. इसके बाद, ऑब्जेक्ट को दोहराया जा रहा है:

const myObject = { "myProperty" : true, "mySecondProperty" : false };
for( const myKey in myObject ) {
  console.log( myKey );
}
> "myProperty"
> "mySecondProperty"

लूप में हर इटरेशन के साथ myKey की वैल्यू बदलने के बावजूद, const का इस्तेमाल बिना किसी गड़बड़ी के किया जा सकता है. ऐसा इसलिए, क्योंकि हर इटरेशन के खत्म होने पर, वैरिएबल को असरदार तरीके से मिटा दिया जाता है. इसके बाद, उसे शुरुआत में फिर से बनाया जाता है.

प्रॉपर्टी की हर कुंजी से जुड़ी वैल्यू, सीधे तौर पर for...in... सिंटैक्स में उपलब्ध नहीं होती. हालांकि, क्योंकि हर इटरेशन में लूप में प्रॉपर्टी कुंजी का ऐक्सेस होता है, इसलिए उस कुंजी का इस्तेमाल उसकी वैल्यू को "खोजने" के लिए किया जा सकता है:

const myObject = { "myProperty" : true, "mySecondProperty" : false };
for( const myKey in myObject ) {
  const myValue = myObject[ myKey ];
  console.log( `${ myKey } : ${ myValue }` );
}
> "myProperty : true"
> "mySecondProperty : false"

पहले से मौजूद कंस्ट्रक्टर से इनहेरिट की गई प्रॉपर्टी की गिनती नहीं की जा सकती है. इसका मतलब है कि for...in..., Object कंस्ट्रक्टर से इनहेरिट की गई प्रॉपर्टी का इस्तेमाल करके दोहराया नहीं जाता. हालांकि, ऑब्जेक्ट की प्रोटोटाइप चेन में मौजूद, गिनती की जा सकने वाली सभी प्रॉपर्टी शामिल हैं:

const myPrototype = { "protoProperty" : true };
const myObject = Object.create( myPrototype, {
    myProperty: {
    value: true,
    enumerable: true
    }
});
for ( const myKey in myObject ) {
  const myValue = myObject[ myKey ];
  console.log( `${ myKey } : ${ myValue }` );
}
> "myProperty : true"
> "protoProperty : true"

JavaScript में पहले से मौजूद ऐसे तरीके मौजूद हैं जिनसे यह पता लगाया जा सकता है कि प्रॉपर्टी, ऑब्जेक्ट के प्रोटोटाइप चेन की प्रॉपर्टी होने के बजाय, ऑब्जेक्ट की डायरेक्ट प्रॉपर्टी है या नहीं: मॉडर्न Object.hasOwn() और लेगसी Object.prototype.hasOwnProperty() तरीके. इन तरीकों से यह आकलन किया जाता है कि कोई खास प्रॉपर्टी इनहेरिट की गई है (या बताई नहीं गई है). यह सिर्फ़ किसी खास ऑब्जेक्ट की तुरंत प्रॉपर्टी के लिए true दिखाती है:

const myPrototype = { "protoProperty" : true };
const myObject = Object.create( myPrototype, {
    myProperty: {
    value: true,
    enumerable: true
    }
});
for ( const myKey in myObject ) {
  const myValue = myObject[ myKey ];
  if ( Object.hasOwn( myObject, myKey ) ) {
    console.log( `${ myKey } : ${ myValue }` );
  }
}
> "myProperty : true"

तीन स्टैटिक तरीके भी होते हैं, जिनसे हर एक ऑब्जेक्ट की गिनती की जा सकने वाली कुंजियों (Object.keys()), वैल्यू (Object.values()) या की-वैल्यू पेयर (Object.entries()) से बना अरे दिखाता है:

const myObject = { "myProperty" : true, "mySecondProperty" : false };
Object.keys( myObject );
> Array [ "myProperty", "mySecondProperty" ]

इससे आपको उस ऑब्जेक्ट के प्रोटोटाइप के मालिकाना हक वाली प्रॉपर्टी को शामिल किए बिना, ऑब्जेक्ट बटन, वैल्यू या की-वैल्यू पेयर को फिर से दोहराने की सुविधा मिलती है (डेटा को नष्ट करने वाले असाइनमेंट का इस्तेमाल करके):

const myPrototype = { "protoProperty" : "Non-enumerable property value." };
const myObject = Object.create( myPrototype, {
    myProperty: {
    value: "Enumerable property value.",
    enumerable: true
    }
});

for ( const propKey of Object.keys( myObject ) ) {
  console.log( propKey );
}
> "myProperty"

for ( const propValue of Object.values( myObject ) ) {
  console.log( propValue );
}
> "Enumerable property value."

for ( const [ propKey, propValue ] of Object.entries( myObject ) ) {
  console.log( `${ propKey } : ${ propValue }` );
}
> "myProperty : Enumerable property value."

forEach()

अरे, मैप, सेट, और NodeList कंस्ट्रक्टर के दिए गए forEach() तरीके, कॉलबैक फ़ंक्शन के मामले में डेटा स्ट्रक्चर को दोहराने के लिए मददगार शॉर्टहैंड उपलब्ध कराते हैं. लूप के दूसरे तरीकों से अलग, किसी भी forEach() तरीके से बनाए गए लूप को break या continue का इस्तेमाल करके रोका नहीं जा सकता.

forEach एक तरीका है जिसका मालिकाना हक हर डेटा स्ट्रक्चर के प्रोटोटाइप के पास होता है. हर forEach तरीके को, आर्ग्युमेंट के तौर पर कॉलबैक फ़ंक्शन की ज़रूरत होती है. हालांकि, फ़ंक्शन को कॉल करते समय, शामिल किए गए तर्कों के हिसाब से ये फ़ंक्शन थोड़े अलग होते हैं. दूसरा, वैकल्पिक तर्क, कॉलबैक फ़ंक्शन के शुरू करने वाले कॉन्टेक्स्ट के तौर पर this वैल्यू तय करता है.

Array.forEach के साथ इस्तेमाल किए गए कॉलबैक फ़ंक्शन में, ऐसे पैरामीटर होते हैं जिनमें मौजूदा एलिमेंट की वैल्यू, मौजूदा एलिमेंट का इंडेक्स, और वह अरे होता है जिस पर forEach तरीके को शुरू किया गया था:

const myArray = [ true, false ];
myArray.forEach( ( myElement, i, originalArray ) => {
  console.log( i, myElement, originalArray  );
});
> 0 true Array(3) [ true, false ]
> 1 false Array(3) [ true, false ]

Map.forEach के साथ इस्तेमाल किया गया कॉलबैक फ़ंक्शन, ऐसे पैरामीटर उपलब्ध कराता है जिनमें मौजूदा एलिमेंट से जुड़ी वैल्यू, मौजूदा एलिमेंट से जुड़ी कुंजी, और forEach तरीके को मैप करने के लिए शुरू किए गए पैरामीटर शामिल होते हैं:

const myMap = new Map([
  ['myKey', true],
  ['mySecondKey', false ],
]);
myMap.forEach( ( myValue, myKey, originalMap ) => {
    console.log( myValue, myKey, originalMap  );
});
> true "myKey" Map { myKey → true, mySecondKey → false }
> false "mySecondKey" Map { myKey → true, mySecondKey → false }

Set.forEach कॉलबैक में मिलते-जुलते पैरामीटर शामिल होते हैं. सेट में वैल्यू से अलग इंडेक्स या कुंजियां नहीं होती हैं. इसलिए, दूसरा आर्ग्युमेंट ग़ैर-ज़रूरी, अनदेखा न की जा सकने वाली वैल्यू देता है, ताकि सिंटैक्स को अन्य forEach तरीकों के हिसाब से रखा जा सके.

const mySet = new Set([ true, false ]);
mySet.forEach( ( myValue, myKey, originalSet ) => {
  console.log( myValue, myKey, originalSet  );
});
> true true Set [ true, false ]
> false false Set [ true, false ]

इटरेटर

अलग-अलग एलिमेंट से बना कोई भी डेटा स्ट्रक्चर उसे बार-बार बदला जा सकता है. इसे फिर से इस्तेमाल किए जा सकते हैं. इसके लिए, पहले बताए गए तरीके का इस्तेमाल किया जा सकता है. इटरेटर एक ऐसा ऑब्जेक्ट है जिसे दोहराया जा सकता है. यह इटरेटर प्रोटोकॉल के मुताबिक होता है. इसका मतलब है कि इसे एक next() वाला तरीका लागू करना होगा, जो एक बार में एक एलिमेंट शामिल होता हो. हर बार उस तरीके को कॉल करने पर, क्रम से चलने वाले हर एलिमेंट के लिए एक खास फ़ॉर्मैट में एक ऑब्जेक्ट देता है.

JavaScript के पहले से मौजूद, फिर से इस्तेमाल किए जा सकने वाले डेटा स्ट्रक्चर (जैसे कि अरे, मैप, और सेट) खुद में इटरेटर नहीं होते, लेकिन वे सभी iterator तरीके से काम करते हैं, जिसे @@iterator लोकप्रिय चिह्न से ऐक्सेस किया जा सकता है. यह फिर से बदलने लायक डेटा स्ट्रक्चर से बनाए गए इटरेटर ऑब्जेक्ट को दिखाता है:

const myIterable = [ 1, 2, 3 ];
const myIterator = myIterable[ Symbol.iterator ]();

myIterable;
> (3) [1, 2, 3]

myIterator;
> Array Iterator {}

इटरेटर पर next() तरीके को कॉल करने से, इसमें एक-एक करके एलिमेंट शामिल होते हैं. हर कॉल में, दो प्रॉपर्टी वाले ऑब्जेक्ट दिखते हैं: value, जिसमें मौजूदा एलिमेंट की वैल्यू होती है और done एक बूलियन होता है, जो हमें यह बताता है कि इटरेटर ने डेटा स्ट्रक्चर के आखिरी एलिमेंट को पास किया है या नहीं. done की वैल्यू true सिर्फ़ तब होती है, जब next() को किए जाने वाले कॉल की वजह से, इटरेटर में मौजूद आखिरी एलिमेंट के अलावा किसी एलिमेंट को ऐक्सेस करने की कोशिश की जाती है.

const myIterable = [ 1, 2, 3 ];
const myIterator = myIterable[ Symbol.iterator ]();

myIterator.next();
> Object { value: 1, done: false }

myIterator.next();
> Object { value: 2, done: false }

myIterator.next();
> Object { value: 3, done: false }

myIterator.next();
> Object { value: undefined, done: true }

जनरेटर के फ़ंक्शन

जनरेटर फ़ंक्शन का एलान करने या जनरेटर फ़ंक्शन एक्सप्रेशन तय करने के लिए, function* कीवर्ड (तारे का निशान नोट करें) का इस्तेमाल करें:

function* myGeneratorFunction() { };

इटरेटर की तरह, जनरेटर फ़ंक्शन स्टेट को बनाए रखते हैं. किसी जनरेटर फ़ंक्शन को कॉल करने से, एक नया जनरेटर ऑब्जेक्ट दिखता है. हालांकि, इससे फ़ंक्शन के मुख्य हिस्से में कोड तुरंत नहीं चलता:

function* myGeneratorFunction() {
  console.log( "Generator function body ")
};
const myGeneratorObject = myGeneratorFunction();

myGeneratorObject;
> Generator {  }

typeof myGeneratorObject;
> "object"

जनरेटर ऑब्जेक्ट, इटरेटर प्रोटोकॉल का पालन करते हैं. जनरेटर फ़ंक्शन पर next() को किए जाने वाले हर कॉल की वैल्यू, yield एक्सप्रेशन से तय की जाती है. इस एक्सप्रेशन से जनरेटर फ़ंक्शन रुक जाता है और yield कीवर्ड वाले एक्सप्रेशन की वैल्यू मिलती है. बाद में कॉल करने पर, next() फ़ंक्शन एक्ज़ीक्यूशन जारी रखता है. साथ ही, अगले yield एक्सप्रेशन पर रोक लगाता है और इससे जुड़ी वैल्यू दिखाता है.

function* myGeneratorFunction() {
  yield "My first yielded value.";
  yield "My second yielded value.";
};
const myGeneratorObject = myGeneratorFunction();

myGeneratorObject.next();
> Object { value: "My first yielded value.", done: false }

myGeneratorObject.next();
> Object { value: "My second yielded value.", done: false }

जब yield, return या throw (गड़बड़ी की स्थिति में) का इस्तेमाल करके कोई और वैल्यू तय न किए जाने के बाद next() को कॉल किया जाता है, तो बाकी के फ़ंक्शन एक्ज़ीक्यूट करते हैं. साथ ही, रिटर्न किए गए ऑब्जेक्ट में undefined का value और true की done प्रॉपर्टी होती है:


function* myGeneratorFunction() {
    console.log( "Start of the generator function." );
    yield "First";
    console.log( "Second part of the generator function."  );
    yield "Second";
    console.log( "Third part of the generator function." );
    yield "Third";
};
const myGeneratorObject = myGeneratorFunction();

myGeneratorObject.next();
> "Start of the generator function."
> Object { value: "First", done: false }

myGeneratorObject.next();
> "Second part of the generator function."
> Object { value: "Second", done: false }

myGeneratorObject.next();
> "Third part of the generator function."
> Object { value: "Third", done: false }

myGeneratorObject.next();
> Object { value: undefined, done: true }

next() का इस्तेमाल सिर्फ़ उस ऑब्जेक्ट पर करें जो जनरेटर फ़ंक्शन दिखाता है, न कि जनरेटर फ़ंक्शन पर. ऐसा न होने पर, जनरेटर फ़ंक्शन को किया जाने वाला हर कॉल, एक नया जनरेटर ऑब्जेक्ट बनाता है:

function* myGeneratorFunction() {
  yield "First";
  yield "Second";
};

myGeneratorFunction().next();
> Object { value: "First", done: false }

myGeneratorFunction().next();
> Object { value: "First", done: false }

किसी भी फ़ंक्शन की तरह ही, जनरेटर फ़ंक्शन को कोई return कीवर्ड मिलने पर रुक जाता है. इसके बाद, यह इस्तेमाल करने वाले कॉन्टेक्स्ट में एक ऑब्जेक्ट दिखाता है. इसमें रिटर्न की गई वैल्यू और true वैल्यू वाली done प्रॉपर्टी होती है.

function* myGeneratorFunction() {
  yield 1;
  yield 2;
  return 3;
};
const myGeneratorObject = myGeneratorFunction();

myGeneratorObject.next().done;
> Object { value: 1, done: false }

myGeneratorObject.next().done;
> Object { value: 2, done: false }

myGeneratorObject.next();
> Object { value: 3, done: true }

yield एक्सप्रेशन, किसी आइडेंटिफ़ायर के कुछ सिमैंटिक इस्तेमाल कर सकता है. इससे, जनरेटर फ़ंक्शन के निलंबित हिस्से से, दोनों तरफ़ "कम्यूनिकेशन" की अनुमति मिल जाती है. जब कोई वैल्यू, जनरेटर के next() तरीके को आर्ग्युमेंट के तौर पर पास की जाती है, तो यह पिछले निलंबित yield एक्सप्रेशन से जुड़ी वैल्यू की जगह ले लेती है:

function* myGeneratorFunction() {
    const firstYield = yield;
    yield firstYield + 10;
};
const myGeneratorObject = myGeneratorFunction();

myGeneratorObject.next();
> Object { value: undefined, done: false }

myGeneratorObject.next( 5 );
> Object { value: 15, done: false }

ध्यान रखें कि यह पिछले yield से जुड़े पूरे एक्सप्रेशन को बदल देता है. साथ ही, न सिर्फ़ पिछले yield की वैल्यू को next() में बताई गई वैल्यू को फिर से असाइन करता है:

function* myGeneratorFunction() {
    const firstYield = yield;
    const secondYield = yield firstYield + 100;
    yield secondYield + 10;
};
const myGeneratorObject = myGeneratorFunction();

myGeneratorObject.next();
> Object { value: undefined, done: false }

myGeneratorObject.next( 10 ); // Can be thought of as changing the value of the `firstYield` variable to `10
> Object { value: 110, done: false }

myGeneratorObject.next( 20 ); // Can be thought of as changing the value of the `secondYield` variable to `20`, _not_ `20 + 100;`
> Object { value: 30, done: false }

next() को पहली कॉल करने पर पास किए गए किसी भी तर्क को अनदेखा कर दिया जाता है, क्योंकि उस वैल्यू को स्वीकार करने के लिए पिछला yield एक्सप्रेशन नहीं होता. किसी भी दूसरे फ़ंक्शन की तरह, शुरुआती जनरेटर फ़ंक्शन कॉल में पास किए गए तर्क, जनरेटर फ़ंक्शन के मुख्य हिस्से में मौजूद होते हैं:

function* myGeneratorFunction( startingValue ) {
    let newValue = yield startingValue + 1;
    newValue = yield newValue + 10;
    yield startingValue + 20;
};
const myGeneratorObject = myGeneratorFunction( 2 );

myGeneratorObject.next( 1 );
> Object { value: 3, done: false }

myGeneratorObject.next( 5 );
> Object { value: 15, done: false }

myGeneratorObject.next( 10 );
Object { value: 22, done: false }

yield* (तारे का निशान नोट करें) ऑपरेटर का इस्तेमाल, बार-बार किए जा सकने वाले किसी अन्य जनरेटर फ़ंक्शन के साथ किया जाता है, ताकि यह ऑपरेंड से मिलने वाली हर वैल्यू को दोहराने और पाने के लिए:

function* mySecondaryGenerator() {
  yield 2;
  yield 3;
}

function* myGenerator() {
  yield 1;
  yield* mySecondaryGenerator();
  yield 4;
  return 5;
}

const myIterator = myGenerator();

myIterator.next();
> Object { value: 1, done: false }

myIterator.next();
> Object { value: 2, done: false }

myIterator.next();
> Object { value: 3, done: false }

myIterator.next();
> Object { value: 4, done: false }

myIterator.next();
> Object { value: 5, done: true }

एसिंक्रोनस JavaScript

हालांकि, JavaScript को एक्ज़ीक्यूट करने में बुनियादी तौर पर एक साथ काम नहीं किया जाता, लेकिन कुछ ऐसे सिस्टम होते हैं जिनकी मदद से डेवलपर, एसिंक्रोनस टास्क करने के लिए इवेंट लूप का फ़ायदा उठा सकते हैं.

वादे

प्रॉमिस ऐसी वैल्यू के लिए प्लेसहोल्डर है जिसे प्रॉमिस बनाए जाने के दौरान पता नहीं चलता. यह एक कंटेनर है, जो एसिंक्रोनस ऑपरेशन को तय करता है. वे शर्तें जिनके ज़रिए कार्रवाई को सफल या असफल माना जाता है, दोनों मामलों में की जाने वाली कार्रवाई, और उससे मिलने वाली वैल्यू के बारे में बताया जाता है.

पहले से मौजूद Promise कंस्ट्रक्टर फ़ंक्शन के साथ new ऑपरेटर का इस्तेमाल करके, Promise इंस्टेंस बनाएं. यह कंस्ट्रक्टर, executor नाम के फ़ंक्शन को तर्क के तौर पर स्वीकार करता है. आम तौर पर, इस एक्ज़ेक्यूटर फ़ंक्शन का इस्तेमाल एक या इससे ज़्यादा एसिंक्रोनस कार्रवाइयां करने के लिए किया जाता है. इसके बाद, वे उन शर्तों को तय करते हैं जिनके ज़रिए प्रॉमिस को पूरा किया जाना चाहिए या अस्वीकार किया जाना चाहिए. एक्ज़ीक्यूटर फ़ंक्शन के चालू रहने के दौरान, प्रॉमिस को मंज़ूरी बाकी कहा जाता है. एक्ज़िक्यूटर के पूरा होने के बाद, प्रॉमिस को पूरा किया गया (या दस्तावेज़ों के कुछ सोर्स में समाधान किया गया) माना जाता है. ऐसा तब होता है, जब एक्ज़ीक्यूटर फ़ंक्शन और एसिंक्रोनस कार्रवाई पूरी तरह से पूरी होती है. साथ ही, अगर एक्ज़ीक्यूटर फ़ंक्शन में कोई गड़बड़ी होती है या एसिंक्रोनस कार्रवाई पूरी नहीं होती है, तो प्रॉमिस को अस्वीकार किया जाता है. वादा पूरा होने या अस्वीकार हो जाने के बाद, उसे सेटलमेंट माना जाता है.

const myPromise = new Promise( () => { });

कंस्ट्रक्टर दो तर्कों के साथ एक्ज़ीक्यूटर फ़ंक्शन को कॉल करता है. ये आर्ग्युमेंट ऐसे फ़ंक्शन होते हैं जिनकी मदद से, प्रॉमिस को मैन्युअल तरीके से पूरा या अस्वीकार किया जा सकता है:

const  myPromise = new Promise( ( fulfill, reject ) => { });

किसी प्रॉमिस को पूरा या अस्वीकार करने के लिए इस्तेमाल किए जाने वाले फ़ंक्शन को आर्ग्युमेंट के तौर पर, प्रॉमिस की नतीजे वाली वैल्यू के साथ कॉल किया जाता है (आम तौर पर, इसे अस्वीकार करने की गड़बड़ी होती है):

const myPromise = new Promise( ( fulfill, reject ) => {
  const myResult = true;
  setTimeout(() => {
    if( myResult === true ) {
        fulfill( "This Promise was successful." );    
    } else {
        reject( new Error( "This Promise has been rejected." ) );
    }
  }, 10000);
});

myPromise;
> Promise { <state>: "pending" }

myPromise;
> Promise { <state>: "fulfilled", <value>: "This Promise was successful." }

प्रॉमिस चेनिंग

इससे बनने वाले प्रॉमिस ऑब्जेक्ट को, प्रॉमिस कंस्ट्रक्टर से इनहेरिट किए गए then(), catch(), और finally() तरीकों का इस्तेमाल करके लागू किया जा सकता है. इनमें से हर तरीका एक प्रॉमिस भेजता है, जिस पर then(), catch() या finally() की मदद से तुरंत कार्रवाई की जा सकती है. इससे, प्रॉमिस को चेन किया जा सकता है.

then(), आर्ग्युमेंट के तौर पर दो कॉलबैक फ़ंक्शन देता है. पहला इस्तेमाल, वादा पूरा करने के लिए और दूसरा उसे अस्वीकार करने के लिए करें. दोनों तरीके एक ही तर्क को स्वीकार करते हैं, जो मिलने वाले प्रॉमिस को उसकी वैल्यू देता है.

const myPromise = new Promise( ( fulfill, reject ) => {
  const myResult = true;
  setTimeout(() => {
    if( myResult === true ) {
        fulfill( "This Promise was fulfilled." );    
    } else {
        reject( new Error( "This Promise has been rejected." ) );
    }
  }, 100);
});

myPromise.then( successfulResult => console.log( successfulResult ), failedResult => console.error( failedResult ) );
> "This Promise was successful."

then() का इस्तेमाल सिर्फ़ ऑर्डर पूरे होने की स्थिति को हैंडल करने के लिए और catch अस्वीकार की गई स्थिति को हैंडल करने के लिए भी किया जा सकता है. catch को एक तर्क के साथ कॉल करें, जिसमें प्रॉमिस के अस्वीकार होने के तरीके में दी गई वैल्यू शामिल है:

const myPromise = new Promise( ( fulfill, reject ) => {
  const myResult = false;
  setTimeout(() => {
    if( myResult === true ) {
        fulfill( "This Promise was fulfilled." );    
    } else {
        reject( new Error( "This Promise has been rejected." ) );
    }
  }, 100);
});

myPromise
  .then( fulfilledResult => console.log(fulfilledResult ) )
  .catch( rejectedResult => console.log( rejectedResult ) )
  .finally( () => console.log( "The Promise has settled." ) );
> "Error: This Promise has been rejected."
> "The Promise has settled."

then और catch में, प्रॉमिस पूरा होने या अस्वीकार होने पर हैंडलर फ़ंक्शन चलाने की अनुमति होती है. वहीं, finally तरीके के लिए आर्ग्युमेंट के तौर पर पास किए गए फ़ंक्शन को कॉल किया जाता है, चाहे प्रॉमिस पूरा हुआ या अस्वीकार किया गया. हैंडलर फ़ंक्शन को बिना किसी आर्ग्युमेंट के कॉल किया जाता है, क्योंकि इसका मकसद प्रॉमिस से पास की गई वैल्यू के साथ काम करना नहीं है. इसका मकसद, सिर्फ़ प्रॉमिस पूरा होने के बाद कोड को एक्ज़ीक्यूट करना है.

समवर्ती

प्रॉमिस कंस्ट्रक्टर एक से ज़्यादा मिलते-जुलते प्रॉमिस के साथ काम करने के चार तरीके बताता है. इसके लिए, प्रॉमिस ऑब्जेक्ट वाले इटरेबल का इस्तेमाल किया जाता है. ये दोनों तरीके एक प्रॉमिस दिखाते हैं, जिसे पास किए गए प्रॉमिस की स्थिति के आधार पर पूरा या अस्वीकार किया जाता है. उदाहरण के लिए, Promise.all() ऐसा प्रॉमिस बनाता है जो सिर्फ़ तब पूरा होता है, जब उस तरीके को पास किया गया हर प्रॉमिस पूरा होता है:

const firstPromise  = new Promise( ( fulfill, reject ) => fulfill( "Successful. ") );
const secondPromise = new Promise( ( fulfill, reject ) => fulfill( "Successful. ") );
const thirdPromise  = new Promise( ( fulfill, reject ) => fulfill( "Successful. ") );
const failedPromise = new Promise( ( fulfill, reject ) => reject( "Failed.") );
const successfulPromises = [ firstPromise, secondPromise, thirdPromise ];
const oneFailedPromise = [ failedPromise, ...successfulPromises ];

Promise.all( successfulPromises )
  .then( ( allValues ) => {
    console.log( allValues );
  })
  .catch( ( failValue ) => {
    console.error( failValue );
  });
> Array(3) [ "Successful. ", "Successful. ", "Successful. " ]

Promise.all( oneFailedPromise  )
    .then( ( allValues ) => {
      console.log( allValues );
    })
    .catch( ( failValue ) => {
     console.error( failValue );
    });
> "Failed."

प्रॉमिस को एक साथ लागू करने के तरीके यहां बताए गए हैं:

Promise.all()
अगर दिए गए सभी प्रॉमिस पूरे हुए, तो ही उन्हें पूरा किया जाएगा.
Promise.any()
अगर दिए गए प्रॉमिस में से कोई एक पूरा होता है, तो उसे पूरा किया जाता है. वहीं, सभी प्रॉमिस को अस्वीकार किए जाने पर ही उसे पूरा किया जाता है.
Promise.allSettled()
जब प्रॉमिस सेटलमेंट के बाद पूरा हो जाता है, तब उसका नतीजा कुछ भी हो सकता है.
Promise.race()
पहले प्रॉमिस का सेटलमेंट होने के आधार पर, उसे अस्वीकार किया गया या पूरा किया गया. इसके अलावा, बाद में सेटलमेंट के सभी प्रॉमिस को अनदेखा किया गया.

async/await

जब फ़ंक्शन के एलान या फ़ंक्शन एक्सप्रेशन से पहले async कीवर्ड का इस्तेमाल किया जाता है, तो फ़ंक्शन से मिलने वाली कोई भी वैल्यू, पूरी किए गए प्रॉमिस के तौर पर दिखती है. इससे आपको सिंक्रोनस डेवलपमेंट वाले वर्कफ़्लो का इस्तेमाल करके एसिंक्रोनस ऑपरेशन चलाने और मैनेज करने की सुविधा मिलती है.

async function myFunction() {
  return "This is my returned value.";
}

myFunction().then( myReturnedValue => console.log( myReturnedValue ) );
> "This is my returned value."

प्रॉमिस को सेट अप करने के दौरान, await एक्सप्रेशन एसिंक्रोनस फ़ंक्शन को रोक देता है. प्रॉमिस सेट होने के बाद, await एक्सप्रेशन की वैल्यू, प्रॉमिस की पूरी या अस्वीकार की गई वैल्यू होती है.

async function myFunction() {
  const myPromise  = new Promise( ( fulfill, reject ) => { setTimeout( () => fulfill( "Successful. "), 5000 ); });
  const myPromisedResult = await myPromise;
  return myPromisedResult;
}

myFunction()
  .then( myResult => console.log( myResult ) )
  .catch( myFailedResult => console.error( myFailedResult ) );
> "Successful."

await एक्सप्रेशन में शामिल बिना प्रॉमिस वैल्यू, पूरे किए गए प्रॉमिस के तौर पर दिखाई जाती है:

async function myFunction() {
  const myPromisedResult = await "String value.";
  return myPromisedResult;
}

myFunction()
  .then( myResult => console.log( myResult ) )
  .catch( myFailedResult => console.error( myFailedResult ) );
> "String value."

जांचें कि आपको कितना समझ आया

किसी जानी-पहचानी संख्या पर दोहराने के लिए किस तरह के लूप का इस्तेमाल किया जाता है?

for
while
do...while