async — Kotlin में एक Coroutine Builder है जो एक कोरूटिन शुरू करता है और एक असिंक्रोनस ऑपरेशन का परिणाम प्राप्त करने के लिए Deferred<T> ऑब्जेक्ट लौटाता है। async एकसाथ अनेक कार्यों को समानांतर रूप से निष्पादित करने और उनके परिणामों को await() के माध्यम से एकत्र करने की अनुमति देता है। JetBrains गाइड, 2024 के अनुसार, async कोरूटिन में समानांतर गणनाओं के आयोजन का पसंदीदा तरीका है।
मुख्य बातें
async — CoroutineScope का एक विस्तार फ़ंक्शन है जो परिणाम लौटाने वाली कोरूटिन बनाता है। launch के विपरीत, async Deferred<T> लौटाता है — एक ऐसा ऑब्जेक्ट जो भविष्य के मान का प्रतिनिधित्व करता है। async के माध्यम से शुरू की गई कोरूटिन अन्य कोरूटिनों के साथ समवर्ती रूप से चलती है, जिससे गणनाओं को समांतरित किया जा सकता है।
async का उपयोग तब किया जाता है जब आगे की प्रसंस्करण के लिए एक असिंक्रोनस ऑपरेशन का परिणाम आवश्यक होता है: एकाधिक स्रोतों से डेटा लोड करना, संग्रहों का बैच प्रसंस्करण, विभिन्न API को समानांतर अनुरोध। Deferred तुरंत बनाया जाता है, और कोरूटिन पूर्ण होने के बाद परिणाम उपलब्ध होता है।
import kotlinx.coroutines.*
suspend fun String.delayedValue(): String {
delay(1000L)
return this
}
fun main() = runBlocking {
val deferred: Deferred<String> = async { "Hello".delayedValue() }
println(deferred.await())
}
async का हस्ताक्षर launch के समान है: वही CoroutineContext, CoroutineStart पैरामीटर और एक suspend ब्लॉक। अंतर रिटर्न प्रकार में है — Job के बजाय Deferred<T>, जहाँ T ब्लॉक के अंतिम एक्सप्रेशन द्वारा लौटाया गया परिणाम प्रकार है।
public fun <T> CoroutineScope.async(
context: CoroutineContext = EmptyCoroutineContext,
start: CoroutineStart = CoroutineStart.DEFAULT,
block: suspend CoroutineScope.() -> T
): Deferred<T>
Deferred<T> — एक इंटरफ़ेस जो Job से विरासत पाता है और await(), getCompleted(), getCompletionExceptionOrNull() विधियाँ जोड़ता है। await() एक suspend फ़ंक्शन है और केवल कोरूटिन या किसी अन्य suspend फ़ंक्शन के अंदर ही बुलाया जा सकता है। getCompleted() एक गैर-अवरोधक विधि है जो अपवाद फेंकती है यदि कोरूटिन अभी पूर्ण नहीं हुई है।
async का मुख्य लाभ कार्यों को समानांतर चलाने की क्षमता है। प्रत्येक ऑपरेशन के अनुक्रमिक रूप से प्रतीक्षा करने के बजाय (कुल समय = समयों का योग), async एकसाथ कोरूटिन शुरू करता है, जिससे कुल समय घटकर सबसे लंबे ऑपरेशन की अवधि के बराबर रह जाता है।
एक सामान्य परिदृश्य — तीन समानांतर async अनुरोधों के साथ उपयोगकर्ता प्रोफ़ाइल, उनकी सेटिंग्स और ऑर्डर हिस्ट्री लोड करना। तीनों के पूर्ण होने के बाद, परिणाम एक ही डेटा मॉडल में संयुक्त हो जाते हैं।
suspend fun loadUserDashboard(userId: String): Dashboard = coroutineScope {
val profile = async { api.getProfile(userId) }
val settings = async { api.getSettings(userId) }
val orders = async { api.getRecentOrders(userId) }
Dashboard(
profile = profile.await(),
settings = settings.await(),
orders = orders.await()
)
}
coroutineScope फ़ंक्शन चाइल्ड कोरूटिन शुरू करता है और परिणाम लौटाने से पहले उनके पूर्ण होने की प्रतीक्षा करता है। पूरा ब्लॉक अनुक्रमिक रूप से नहीं, बल्कि समानांतर रूप से निष्पादित होता है।
Deferred परिणाम के साथ कार्य करने के लिए अनेक विधियों का समर्थन करता है। await() के अलावा, स्थिति की जाँच करने, पूर्ण मान प्राप्त करने और Kotlin Coroutines उपयोगिता फ़ंक्शनों के माध्यम से एकाधिक Deferred को एकत्र करने के लिए विधियाँ उपलब्ध हैं।
| विधि | विवरण | Suspend? |
|---|---|---|
| await() | परिणाम मिलने तक कोरूटिन को रोकता है | हाँ |
| getCompleted() | यदि कोरूटिन पूर्ण हो गई है तो परिणाम लौटाता है (अन्यथा Exception) | नहीं |
| getCompletionExceptionOrNull() | त्रुटि पर अपवाद या null लौटाता है | नहीं |
| isCompleted | जाँचता है कि कोरूटिन पूर्ण हुई है या नहीं | नहीं |
Deferred की सूची को एकत्र करने के लिए, awaitAll() का उपयोग किया जाता है — एक फ़ंक्शन जो संग्रह में सभी Deferred के पूर्ण होने तक निष्पादन को रोकता है। यदि कम से कम एक त्रुटि के साथ पूर्ण होता है, तो awaitAll() अपवाद फेंकता है।
suspend fun <T> loadAll(requests: List<suspend () -> T>): List<T> {
return coroutineScope {
val deferreds = requests.map { async { it() } }
deferreds.awaitAll()
}
}
async और launch के बीच चुनाव इस बात पर निर्भर करता है कि कोरूटिन का परिणाम आवश्यक है या नहीं। launch Job लौटाता है और fire-and-forget ऑपरेशनों के लिए उपयुक्त है, async Deferred लौटाता है और डेटा लौटाने वाले कार्यों के लिए उपयोग किया जाता है। सिंटैक्स और पैरामीटरों के संदर्भ में, बिल्डर समान हैं।
महत्वपूर्ण नियम: fire-and-forget के लिए async का उपयोग कभी न करें। यदि कोरूटिन का परिणाम आवश्यक नहीं है, तो launch का उपयोग करें। async Deferred बनाने का ओवरहेड बनाता है, जो ऐसे परिदृश्यों में उचित नहीं है।
Android में, async का उपयोग ViewModel और UseCases के अंदर समानांतर संचालनों के लिए किया जाता है। सामान्य परिदृश्य: एकसाथ प्रोफ़ाइल और न्यूज़ फ़ीड लोड करना, एकाधिक मौसम सेवाओं से मौसम प्राप्त करना, सर्वर के साथ बैच डेटा सिंक्रोनिजेशन।
class HomeViewModel : ViewModel() {
fun loadHomeScreen() {
viewModelScope.launch {
val userData = async(Dispatchers.IO) { repository.getUserData() }
val newsFeed = async(Dispatchers.IO) { repository.getNewsFeed() }
val notifications = async(Dispatchers.IO) { repository.getNotifications() }
val state = HomeState(
user = userData.await(),
news = newsFeed.await(),
unread = notifications.await()
)
_uiState.update { state }
}
}
}
त्रुटि पृथक्करण के लिए async के एक समूह को coroutineScope या supervisorScope में लपेटने की अनुशंसा की जाती है। supervisorScope शेष async कोरूटिनों को जारी रखने की अनुमति देता है भले ही एक विफल हो जाए — गैर-महत्वपूर्ण संचालनों के लिए उपयोगी।
अक्सर पूछे जाने वाले प्रश्न
किया जा सकता है, लेकिन यह बेकार है। async बिना await() के एक कोरूटिन शुरू करता है लेकिन उसका परिणाम खो जाता है। यदि परिणाम की आवश्यकता नहीं है, तो launch का उपयोग करें — यह Deferred नहीं बनाता और मेमोरी और प्रदर्शन में अधिक कुशल है।
async के अंदर एक अपवाद Deferred में संग्रहीत हो जाता है। await() को कॉल करने पर यह अपवाद फेंकता है। बिना फेंके जाँच करने के लिए getCompletionExceptionOrNull() का उपयोग करें। coroutineScope का उपयोग करते समय, एक त्रुटि सभी चाइल्ड कोरूटिनों को रद्द कर देती है।
awaitAll() — Iterable<Deferred<T>> के लिए एक विस्तार फ़ंक्शन जो सभी Deferred के पूर्ण होने तक कोरूटिन को रोकता है। परिणामों की एक सूची लौटाता है। यदि कम से कम एक Deferred विफल होता है, तो यह अपवाद फेंकता है और बाकी को रद्द करता है।
हाँ। async, CoroutineScope का एक विस्तार फ़ंक्शन है जो दायरे से बंधा होता है। GlobalScope.async जीवन चक्र से बिना जुड़े एक कोरूटिन बनाता है — यह अनियमित रूप से चल सकता है। लीक के जोखिम के कारण Android में GlobalScope की अनुशंसा नहीं की जाती है।
संख्या डिस्पैचर द्वारा निर्धारित की जाती है: Dispatchers.IO 64 समवर्ती थरेड्स तक का समर्थन करता है, Dispatchers.Default — CPU कोर की संख्या तक। बल्क ऑपरेशनों के लिए, Semaphore या awaitAll के साथ mapNotNull के माध्यम से सीमित समानांतरता का उपयोग करें।
सारांश
हम एक मोबाइल एप्लिकेशन टर्नकी विकसित करेंगे
IT Sectr 2017 से स्टार्टअप और व्यवसायों के लिए iOS और Android एप्लिकेशन बनाता है। हम आपको सलाह देंगे और सर्वोत्तम समाधान प्रस्तावित करेंगे।
यह भी पढ़ें