Suspend function एक ऐसा फंक्शन है जिसमें suspend मॉडिफ़ायर होता है जो थ्रेड को ब्लॉक किए बिना अपने निष्पादन को रोक सकता है और बाद में उसी कोरुटीन में फिर से शुरू कर सकता है। JetBrains Kotlin Docs, 2025 के अनुसार, सस्पेंड फंक्शन कोरुटीन के मूलभूत निर्माण खंड हैं, जो कॉलबैक के बिना अतुल्यकालिकता प्रदान करते हैं। प्रत्येक सस्पेंड फंक्शन Continuation पर आधारित स्टेट मशीन में संकलित होता है, जो सस्पेंशन पॉइंट्स के कुशल प्रबंधन की अनुमति देता है।
मुख्य बिंदु
Suspend function एक ऐसा फंक्शन है जिसे suspend कीवर्ड के साथ घोषित किया गया है जो थ्रेड को ब्लॉक किए बिना एक या अधिक बिंदुओं पर निष्पादन रोक सकता है। दूसरे सस्पेंड फंक्शन के अंदर सस्पेंड फंक्शन का प्रत्येक कॉल एक संभावित सस्पेंशन पॉइंट है।
suspend fun fetchUserData(): User {
val response = httpClient.get("/user")
return parser.parse(response)
}
Kotlin कंपाइलर ऐसे फंक्शन को स्टेट मशीन में अनुवादित करता है। प्रत्येक सस्पेंशन पॉइंट (दूसरे सस्पेंड फंक्शन का कॉल) एक स्टेट (label) बन जाता है। वर्तमान थ्रेड स्टेट्स के बीच रिलीज़ होता है, और प्रतीक्षित ऑपरेशन पूरा होने के बाद, निष्पादन अगले स्टेट से फिर से शुरू होता है।
सस्पेंड फंक्शन Kotlin 1.3 (2018) में कोरुटीन के साथ एक प्रयोगात्मक सुविधा के रूप में दिखाई दिए और Kotlin 1.5 (2021) में स्थिर हो गए। इससे पहले, Kotlin/Java में अतुल्यकालिकता कॉलबैक, RxJava और CompletableFuture के माध्यम से प्राप्त की जाती थी। सस्पेंड फंक्शन ने रैखिक सिंटैक्स और स्वचालित थ्रेड प्रबंधन के साथ एक विकल्प प्रस्तुत किया।
सस्पेंड फंक्शन की आंतरिक कार्यप्रणाली को समझना कोरुटीन के साथ सही ढंग से काम करने की कुंजी है। सामान्य फंक्शन के विपरीत, प्रत्येक सस्पेंड फंक्शन Continuation इंटरफ़ेस वाली क्लास में संकलित होता है।
Kotlin कंपाइलर प्रत्येक सस्पेंड फंक्शन के पैरामीटर सूची के अंत में Continuation प्रकार का एक पैरामीटर जोड़ता है। Continuation में शामिल है:
मान लीजिए हमारे पास दो अन्य सस्पेंड फंक्शन के कॉल वाला एक सस्पेंड फंक्शन है:
suspend fun process() {
val a = stepOne()
val b = stepTwo(a)
println(b)
}
कंपाइलर इसे लेबल के साथ स्टेट मशीन में बदल देता है:
// Simplified generated code representation
fun process(cont: Continuation<Unit>): Any? {
val cont = cont as ProcessContinuation
when (cont.label) {
0 -> {
cont.label = 1
if (stepOne(cont) == COROUTINE_SUSPENDED) return COROUTINE_SUSPENDED
}
1 -> {
cont.label = 2
val a = cont.result as TypeA
if (stepTwo(a, cont) == COROUTINE_SUSPENDED) return COROUTINE_SUSPENDED
}
2 -> {
println(cont.result)
Unit
}
}
}
मुख्य अवलोकन: यदि फंक्शन COROUTINE_SUSPENDED लौटाता है, तो वर्तमान थ्रेड रिलीज़ हो जाता है। जब अतुल्यकालिक ऑपरेशन पूरा हो जाता है, Continuation.resumeWith कॉल किया जाता है, और स्टेट मशीन अगले लेबल से जारी रहती है।
सस्पेंड फंक्शन घोषित करना सामान्य फंक्शन से अलग नहीं है, सिवाय fun से पहले suspend कीवर्ड के। केवल एक प्रतिबंध है: सस्पेंड फंक्शन को केवल कोरुटीन या किसी अन्य सस्पेंड फंक्शन से ही कॉल किया जा सकता है।
suspend fun delayAndReturn(ms: Long): String {
delay(ms)
return "Done after ${ms}ms"
}
इस उदाहरण में, delay भी एक सस्पेंड फंक्शन है जो थ्रेड को ब्लॉक किए बिना निर्दिष्ट मिलीसेकंड के लिए कोरुटीन को रोकता है। देरी के बाद, निष्पादन फिर से शुरू होता है।
fun main() = runBlocking {
val result = delayAndReturn(1000)
println(result)
}
runBlocking सामान्य दुनिया और कोरुटीन के बीच एक पुल बनाता है। lambda के अंदर, किसी भी सस्पेंड फंक्शन को कॉल किया जा सकता है।
Kotlin कार्यात्मक प्रकारों के सस्पेंड संस्करणों का समर्थन करता है — suspend () -> T और suspend (A) -> B. यह उच्च-क्रम वाले फंक्शन में अतुल्यकालिक लैम्ब्डा पास करने की अनुमति देता है:
suspend fun withRetry (
retries: Int = 3,
block: suspend () -> T
): T {
repeat(retries - 1) {
try { return block() }
catch (_: Exception) { delay(100) }
}
return block()
}
withRetry फंक्शन एक सस्पेंड लैम्ब्डा लेता है और त्रुटियों पर इसके निष्पादन का पुनः प्रयास करता है। यह पुनः प्रयास के साथ नेटवर्क अनुरोधों के लिए एक विशिष्ट पैटर्न है।
सस्पेंड और सामान्य फंक्शन के बीच अंतर केवल एक मॉडिफ़ायर जोड़ने से परे हैं। आइए मुख्य अंतरों को देखें।
| विशेषता | सामान्य फंक्शन | सस्पेंड फंक्शन |
|---|---|---|
| निष्पादन थ्रेड | पूरा होने तक थ्रेड को ब्लॉक करता है | थ्रेड को छोड़ सकता है और बाद में फिर से शुरू कर सकता है |
| कंपाइलर पैरामीटर | केवल निर्दिष्ट पैरामीटर | अंत में अंतर्निहित Continuation |
| सामान्य फंक्शन से कॉल | हाँ | नहीं |
| स्टैक | भौतिक थ्रेड स्टैक | हीप में स्टेट मशीन + बिंदुओं के बीच भौतिक स्टैक |
| वापसी मान | प्रत्यक्ष मान | मान या COROUTINE_SUSPENDED |
| प्रदर्शन | न्यूनतम ओवरहेड | ~कुछ नैनोसेकंड प्रति स्टेट मशीन (Kotlin 1.9+) |
सामान्य फंक्शन में Continuation नहीं होता — उसके पास स्टेट सहेजने के लिए कोई स्थान नहीं है और निष्पादन फिर से शुरू करने के लिए कुछ भी नहीं है। यदि आपको सामान्य फंक्शन से सस्पेंड फंक्शन कॉल करने की आवश्यकता है, तो runBlocking (परीक्षण के लिए) या CoroutineScope.launch (जीवनचक्र जागरूकता के साथ उत्पादन के लिए) का उपयोग करें।
आइए Kotlin के साथ Android ऐप्स में सस्पेंड फंक्शन का उपयोग करने के तीन वास्तविक परिदृश्य देखें।
Room सीधे सस्पेंड फंक्शन का समर्थन करता है — क्वेरी स्वचालित रूप से पृष्ठभूमि थ्रेड पर निष्पादित होती है:
@Dao
interface UserDao {
@Query("SELECT * FROM users WHERE id = :id")
suspend fun getUser(id: Int): User?
@Insert
suspend fun insertUser(user: User)
}
Room आंतरिक रूप से क्वेरी निष्पादित करने के लिए Dispatchers.IO का उपयोग करता है, और परिणाम उस डिस्पैचर पर लौटाया जाता है जहाँ सस्पेंड फंक्शन कॉल किया गया था।
class ProfileViewModel : ViewModel() {
private val repo = ProfileRepository()
fun loadProfile(id: String) {
viewModelScope.launch {
val profile = repo.getProfile(id)
_profile.value = profile
}
}
}
ViewModelScope.launch एक कोरुटीन बनाता है, जिसके अंदर getProfile सस्पेंड फंक्शन कॉल किया जाता है। परिणाम प्राप्त करने के बाद, UI मुख्य थ्रेड पर अपडेट होता है।
suspend fun placeOrder(cart: Cart): OrderResult {
val validated = validateCart(cart)
val payment = processPayment(validated)
val receipt = sendReceipt(payment)
return receipt
}
तीन सस्पेंड फंक्शन क्रमिक रूप से निष्पादित होते हैं। प्रत्येक चरण पर, कोरुटीन थ्रेड को ब्लॉक किए बिना रुक सकता है। यदि कोई चरण अपवाद फेंकता है, तो शेष चरण निष्पादित नहीं होते, जो गलत ऑर्डर स्थितियों से बचाता है।
अनुभवी Kotlin डेवलपर भी सस्पेंड फंक्शन डिज़ाइन करते समय गलतियाँ करते हैं। आइए सबसे सामान्य गलतियाँ देखें।
सस्पेंड फंक्शन कोड को स्वचालित रूप से अतुल्यकालिक नहीं बनाता। Thread.sleep(), InputStream.read() और अन्य ब्लॉकिंग कॉल अभी भी थ्रेड को ब्लॉक करेंगे। ब्लॉकिंग ऑपरेशन को लपेटने के लिए withContext(Dispatchers.IO) का उपयोग करें।
यदि कोई फंक्शन अन्य सस्पेंड फंक्शन को कॉल नहीं करता और अतुल्यकालिक ऑपरेशन नहीं करता — तो सस्पेंड मॉडिफ़ायर अनावश्यक है। यह स्टेट मशीन के लिए ओवरहेड जोड़ता है और कॉलिंग संदर्भ को प्रतिबंधित करता है। फंक्शन को तभी सस्पेंड बनाएं जब वह वास्तव में रुकता हो।
जब कोरुटीन रद्द किया जाता है, सस्पेंड फंक्शन CancellationException फेंकते हैं। इसे बिना सोचे समझे न पकड़ें — आप कॉलिंग कोड को रद्दीकरण को ठीक से पूरा करने की क्षमता से वंचित कर रहे हैं। यदि आपको अंतिमकरण ऑपरेशन करने की आवश्यकता है, तो finally ब्लॉक और NonCancellable का उपयोग करें।
suspend fun safeOperation() {
try {
doWork()
} finally {
withContext(NonCancellable) {
cleanup()
}
}
}
finally ब्लॉक हमेशा निष्पादित होता है, रद्दीकरण पर भी, और NonCancellable सुनिश्चित करता है कि सफाई बाधित न हो।
आप कोरुटीन बनाए बिना सीधे कॉलबैक से सस्पेंड फंक्शन कॉल नहीं कर सकते। कॉलबैक शैली को कोरुटीन के अनुकूल बनाने के लिए suspendCoroutine या suspendCancellableCoroutine का उपयोग करें।
अक्सर पूछे जाने वाले प्रश्न
हाँ, तकनीकी रूप से सस्पेंड फंक्शन अन्य सस्पेंड फंक्शन को कॉल नहीं कर सकता। कंपाइलर एकल स्टेट (label 0) के साथ स्टेट मशीन बनाएगा। हालाँकि, ऐसे फंक्शन का कोई व्यावहारिक लाभ नहीं है — यह सामान्य फंक्शन की तरह चलता है लेकिन ओवरहेड के साथ। बिना आवश्यकता के सस्पेंड का उपयोग न करें।
Kotlin kotlinx-coroutines-debug प्रदान करता है — DebugProbes और कोरुटीन ट्रेसिंग टूल वाली एक लाइब्रेरी। Android Studio में Arctic Fox से, डिबगर में एक अंतर्निहित Coroutines टैब है जो सक्रिय कोरुटीन, उनकी स्थिति और सस्पेंशन पॉइंट दिखाता है।
प्रत्येक सस्पेंशन पॉइंट स्टेट मशीन में एक नया स्टेट बनाता है। अधिकांश अनुप्रयोगों के लिए, एक पॉइंट का ओवरहेड कुछ नैनोसेकंड है (Kotlin 1.9+)। केवल लूप में दसियों हज़ार पॉइंट के साथ आपको ऑपरेशन संयोजित करने या sequence/flow का उपयोग करने पर विचार करना चाहिए।
Kotlin में, suspend एक फंक्शन प्रकार मॉडिफ़ायर है, न कि रिटर्न वैल्यू मार्कर (जैसे C# में async)। कोई भी सस्पेंड फंक्शन किसी भी पैरामीटर और रिटर्न प्रकार ले सकता है, और इसका कॉल वाक्यगत रूप से सामान्य फंक्शन कॉल से अलग नहीं है — कॉल साइट पर कोई await ऑपरेटर नहीं है।
अनुकूलन के लिए suspendCancellableCoroutine का उपयोग करें। अंदर, आप एक कॉलबैक पंजीकृत करते हैं जो continuation.resume() को कॉल करता है, और यदि कॉलबैक सब्सक्रिप्शन रद्द करने का समर्थन करता है तो एक रद्दीकरण टोकन लौटाते हैं। यह पुराने Android API को लपेटने का मानक पैटर्न है।
सारांश
हम एक मोबाइल एप्लिकेशन टर्नकी विकसित करेंगे
IT Sectr 2017 से स्टार्टअप और व्यवसायों के लिए iOS और Android एप्लिकेशन बनाता है। हम आपको सलाह देंगे और सर्वोत्तम समाधान प्रस्तावित करेंगे।
यह भी पढ़ें