एक async फ़ंक्शन के बाहर प्रतीक्षा का उपयोग करना


86

मैं दो async फ़ंक्शंस को एक साथ करने का प्रयास कर रहा था, क्योंकि पहले में एक सशर्त रिटर्न पैरामीटर था जो दूसरे को चलाने के लिए या मॉड्यूल से बाहर निकलने का कारण था। हालाँकि, मुझे अजीब व्यवहार मिला है जो मैं ऐनक में नहीं ढूँढ सकता।

async function isInLobby() {
    //promise.all([chained methods here])
    let exit = false;
    if (someCondition) exit = true;
}

यह मेरे कोड का एक कमिटेड स्निपेट है (आप यहां पूरा स्कोप देख सकते हैं ), जो कि पहले से ही एक लॉबी में अगर कोई खिलाड़ी है तो जांच करता है, लेकिन यह अप्रासंगिक है।

अगला हमारे पास यह async फ़ंक्शन है।

async function countPlayer() {
    const keyLength = await scardAsync(game);
    return keyLength;
}

इस फ़ंक्शन को यदि चलाने की आवश्यकता नहीं है exit === true

मैंने करने की कोशिश की

const inLobby = await isInLobby();

मुझे आशा थी कि मुझे परिणामों की प्रतीक्षा होगी, इसलिए मैं inLobbyसशर्त रूप से चलाने के लिए उपयोग कर सकता हूं countPlayer, हालांकि मुझे कोई विशिष्ट विवरण नहीं मिला।

क्यों नहीं कर सकते हैं आप awaitएक asyncसमारोह के दायरे से बाहर समारोह? मुझे पता है कि यह एक चीनी का वादा है, इसलिए इसे जंजीर होना चाहिए, thenलेकिन ऐसा क्यों है कि countPlayerमैं एक और वादा कर सकता हूं, लेकिन बाहर, मैं नहीं कर सकता await isInLobby?


क्या आप हमें दिखा सकते हैं कि आपने क्या किया await isInLobby(), और inLobbyइसका उपयोग कैसे किया जाता है? इसके अलावा, कहाँ / कैसे countPlayerकहा जाता है?
Bergi

@ बर्गी मैंने अपने रेपो को वास्तविक संदर्भ के लिए जोड़ा। प्रश्न में डालने के लिए बहुत अधिक कोड
स्टर्लिंग आर्चर

मैं नहीं देखता कि समस्या कहाँ है (शायद आप पहले से ही रेपो को अपडेट कर चुके हैं)? यदि आप isInLobby().then( … countPlayer().then …भाग को संदर्भित करते हैं, तो समाधान तुच्छ है: बस उस फ़ंक्शन को बनाएं जिसमें वे कॉल समाहित हैं ( (req, res) =>एक) async
बरगी

@Bergi मुद्दा यह नहीं है कि यह टूट गया था, यह काम करता है। मुझे समझ में नहीं आया कि शीर्ष-स्तर की प्रतीक्षा क्यों नहीं की गई। बाहर निकलता है यह सिर्फ एक async फ़ंक्शन के रूप में अपने पूरे मॉड्यूल को स्कूप किए बिना अभी तक मौजूद नहीं है
स्टर्लिंग आर्चर

लेकिन आपको अपने कोड के लिए शीर्ष स्तर की भी आवश्यकता नहीं है await? इसलिए मुझे आश्चर्य है कि आपने उस प्रश्न को स्वीकार कर लिया जो वास्तव में प्रश्न में समस्या से संबंधित नहीं है।
बरगी

जवाबों:


73

शीर्ष स्तर awaitसमर्थित नहीं है। इस बारे में मानक समिति द्वारा कुछ चर्चाएँ हैं, जैसे कि यह गितूब मुद्दा

Github पर एक विचारधारा भी है कि शीर्ष स्तर की प्रतीक्षा क्यों एक बुरा विचार है। विशेष रूप से वह सुझाव देता है कि यदि आपके पास इस तरह का कोड है:

// data.js
const data = await fetch( '/data.json' );
export default data;

अब कोई भी फ़ाइल जो आयात करती है data.js, जब तक कि भ्रूण पूरा नहीं हो जाता है, तब तक आपके सभी मॉड्यूल लोड करना बंद हो जाता है। यह एप्लिकेशन मॉड्यूल ऑर्डर के बारे में तर्क देना बहुत मुश्किल है, क्योंकि हम शीर्ष स्तर के जावास्क्रिप्ट को सिंक्रोनाइज़ और अनुमानित रूप से निष्पादित कर रहे हैं। यदि यह अनुमति दी गई है, जब एक समारोह परिभाषित हो जाता है जानना मुश्किल हो जाता है।

मेरा नजरिया यह है कि आपके मॉड्यूल के लिए इसे लोड करके साइड इफेक्ट होना बुरा है। इसका मतलब है कि आपके मॉड्यूल के किसी भी उपभोक्ता को आपके मॉड्यूल की आवश्यकता के अनुसार साइड इफेक्ट मिलेंगे। यह बुरी तरह से सीमित है जहां आपके मॉड्यूल का उपयोग किया जा सकता है। एक शीर्ष स्तर का awaitमतलब है कि आप कुछ एपीआई से पढ़ रहे हैं या लोड समय पर किसी सेवा को कॉल कर रहे हैं इसके बजाय आपको बस एसिंक्स कार्यों का निर्यात करना चाहिए जो उपभोक्ता अपनी गति से उपयोग कर सकते हैं।


यह एक अच्छी कड़ी है, धन्यवाद। यह शर्म की बात है शीर्ष स्तर का समर्थन नहीं है। मैं आशा करती हूं यह है। वर्तमान में जैसा कि यह है कि मुझे अपने वादे यहाँ घोंसले में रखने हैं और यह बहुत बुरा व्यवहार है और मुझे यह पसंद नहीं है। :( धन्यवाद।
स्टर्लिंग आर्चर

: @SterlingArcher वैकल्पिक रूप से, एक async Iife का उपयोगvoid async function() { const inLobby = await isInLobby() }()
robertklep

@robertklep inLobbyफ़ंक्शन के उस दायरे को गैर-सुलभ नहीं बनायेगा ?
स्टर्लिंग आर्चर

@SterlingArcher हाँ, यह होगा, इससे आपको अपने सभी कोड को स्थानांतरित करने की आवश्यकता होगी (मूल रूप से इसे "शीर्ष स्तर")। यह सिर्फ उपयोग करने का एक विकल्प है .then()(क्षमा करें, इसे थोड़ा और स्पष्ट करना चाहिए)।
रोबर्टकेलेप

सहमत न हों, data.js का उपयोगकर्ता डेटा को लोड करते समय फिर भी 'अवरुद्ध' किया जाता है। स्वयं और उसकी निर्भरता के सभी, 'अवरुद्ध' की यह धारणा अपने आप में खराब नहीं है। शीर्ष स्तर की प्रतीक्षा को कुछ निर्भरता को लोड करने के रूप में माना जा सकता है, जिसका उपयोग करने से पहले एक व्यक्ति को होना चाहिए।
इब्राहिम बेन सलाह

125

वहाँ हमेशा इस पाठ्यक्रम है:

(async () => {
    await ...

    // all of the script.... 

})();
// nothing else

यह async के साथ एक त्वरित कार्य करता है जहाँ आप प्रतीक्षा कर सकते हैं। यह आपको एक async फ़ंक्शन बनाने की आवश्यकता को बचाता है जो बहुत अच्छा है! // क्रेडिट Silve2611


3
कृपया आगे विस्तार से बताएं और बताएं कि यह क्यों काम करता है।
पॉल बैक

12
इस जवाब को डाउनवोट करना बहुत बेवकूफी है। यह async के साथ एक त्वरित कार्य करता है जहाँ आप प्रतीक्षा कर सकते हैं। यह आपको एक async फ़ंक्शन बनाने की आवश्यकता को बचाता है जो बहुत अच्छा है!
सिल्वे २६११ ४'१

55
समस्या को हल नहीं करता है क्योंकि आपको अभी भी awaitइस अनाम फ़ंक्शन की आवश्यकता है , जो फिर से, कार्यों के बाहर से काम नहीं करता है।
माइकल

तो यह कैसे एक त्रुटि स्थिति को संभालना होगा? क्या यह भी प्रतीक्षित कोड के अंदर उतरता है?
मैनुअल हर्नांडेज

टी.के.एस इस greate मदद विशेष रूप से कालबैक में वादा एक बार लॉगिन एपीआई, जो प्रतिक्रिया वापस पूरी तरह से है भंडारण GetItem प्राप्त करने के लिए लाने के लिए है,
टेस सू

9

इससे भी बेहतर कोड ब्लॉक के सामने अतिरिक्त अर्धविराम लगाना है

;(async () => {
    await ...
})();

यह पिछली पंक्ति के अंत में पहली पेरेंटहिस को स्थानांतरित करने के लिए ऑटो-फॉर्मैटर (उदाहरण के लिए vscode) को रोकता है।

समस्या को निम्न उदाहरण पर प्रदर्शित किया जा सकता है:

const add = x => y => x+y
const increment = add(1)
(async () => {
    await ...
})();

अर्धविराम के बिना, इसे फिर से स्वरूपित किया जाएगा:

const add = x => y => x+y
const increment = add(1)(async () => {
  await Promise(1)
})()

जो स्पष्ट रूप से गलत है क्योंकि यह async फ़ंक्शन को yपैरामीटर के रूप में निर्दिष्ट करता है और परिणाम से फ़ंक्शन को कॉल करने की कोशिश करता है (जो वास्तव में एक अजीब स्ट्रिंग है '1async () => {...}')


20
यह सुधारक नहीं है जो गलत है। अर्धविराम के बिना, यह है कि आपके फ़ंक्शन को रनटाइम में पार्स किया जाएगा, और आपको एक त्रुटि, लाइन ब्रेक या कोई लाइन ब्रेक नहीं मिलेगा। आपके उदाहरण में सही समाधान यह होगा add(1);कि एसिंक्स फ़ंक्शन के पहले और बाद में अर्धविराम जोड़ना होगा ।
मदारा का भूत

11
इसके अलावा, मैं ईमानदारी से यह नहीं समझता कि यह सवाल हाथ से कैसे संबंधित है।
मदार का भूत 12

हाँ तुम सही हो। इसके अलावा रनटाइम को अर्धविराम की जरूरत होती है।
विलिअम सिमको


1

आप टाइप करने के बाद से शीर्ष स्तर का इंतजार कर सकते हैं। 3.8
https://www.typescriptlang.org/docs/handbook/release-notes/typescript-3-8.html#-top-level-await
इस पोस्ट से:
यह पहले से है जावास्क्रिप्ट (एक समान सुविधा के साथ अधिकांश अन्य भाषाओं के साथ), एसिट फ़ंक्शन के शरीर के भीतर केवल प्रतीक्षा की अनुमति थी। हालांकि, शीर्ष-स्तरीय प्रतीक्षा के साथ, हम किसी मॉड्यूल के शीर्ष स्तर पर प्रतीक्षा का उपयोग कर सकते हैं।

const response = await fetch("...");
const greeting = await response.text();
console.log(greeting);

// Make sure we're a module
export {};

ध्यान दें कि एक सूक्ष्मता है: शीर्ष-स्तर प्रतीक्षा केवल एक मॉड्यूल के शीर्ष स्तर पर काम करती है, और फ़ाइलों को केवल मॉड्यूल माना जाता है जब टाइपस्क्रिप्ट आयात या निर्यात पाता है। कुछ बुनियादी मामलों में, आपको यह सुनिश्चित करने के लिए कुछ बायलरप्लेट के रूप में एक्सपोर्ट {} लिखना होगा।

शीर्ष स्तर का इंतजार उन सभी वातावरणों में काम नहीं कर सकता है जहाँ आप इस बिंदु पर उम्मीद कर सकते हैं। वर्तमान में, आप केवल शीर्ष स्तर की प्रतीक्षा का उपयोग कर सकते हैं जब लक्ष्य संकलक विकल्प es2017 या उससे ऊपर है, और मॉड्यूल esnext या सिस्टम है। कई वातावरण और बंडलों के भीतर समर्थन सीमित हो सकता है या प्रयोगात्मक समर्थन को सक्षम करने की आवश्यकता हो सकती है।

हमारी साइट का प्रयोग करके, आप स्वीकार करते हैं कि आपने हमारी Cookie Policy और निजता नीति को पढ़ और समझा लिया है।
Licensed under cc by-sa 3.0 with attribution required.