Scala Language
फ्यूचर्स
खोज…
भविष्य बनाना
import scala.concurrent.Future
import scala.concurrent.ExecutionContext.Implicits.global
object FutureDivider {
def divide(a: Int, b: Int): Future[Int] = Future {
// Note that this is integer division.
a / b
}
}
काफी बस, divide
विधि एक भविष्य बनाता है जो a
ओवर b
के भागफल के साथ हल करेगा।
एक सफल भविष्य का उपभोग करना
एक सफल Future-- या बल्कि उपभोग करने का सबसे आसान तरीका, Future-- के अंदर मूल्य प्राप्त करना है - map
विधि का उपयोग करना है। मान लीजिए कि कुछ कोड FutureDivider
ऑब्जेक्ट के divide
विधि को "क्रिएटिंग ए फ्यूचर" उदाहरण से कहते हैं। a
ओवर b
के भागफल प्राप्त करने के लिए कोड को क्या देखना होगा?
object Calculator {
def calculateAndReport(a: Int, b: Int) = {
val eventualQuotient = FutureDivider divide(a, b)
eventualQuotient map {
quotient => println(quotient)
}
}
}
असफल भविष्य का उपभोग करना
कभी-कभी Future में गणना एक अपवाद बना सकती है, जिससे Future विफल हो जाएगा। "क्रिएटिंग ए फ्यूचर" उदाहरण में, कॉलिंग कोड 55
और 0
को divide
करने की विधि से गुजरने पर क्या होगा? यह शून्य से विभाजित करने की कोशिश के बाद एक ArithmeticException
फेंक देगा, निश्चित रूप से। कैसे उपभोग कोड में संभाला जाएगा? विफलताओं से निपटने के लिए वास्तव में मुट्ठी भर तरीके हैं।
recover
और पैटर्न मिलान के साथ अपवाद को संभालें।
object Calculator {
def calculateAndReport(a: Int, b: Int) = {
val eventualQuotient = FutureDivider divide(a, b)
eventualQuotient recover {
case ex: ArithmeticException => println(s"It failed with: ${ex.getMessage}")
}
}
}
failed
प्रक्षेपण के साथ अपवाद को संभालें, जहां अपवाद भविष्य का मूल्य बन जाता है:
object Calculator {
def calculateAndReport(a: Int, b: Int) = {
val eventualQuotient = FutureDivider divide(a, b)
// Note the use of the dot operator to get the failed projection and map it.
eventualQuotient.failed.map {
ex => println(s"It failed with: ${ex.getMessage}")
}
}
}
भविष्य को एक साथ रखना
पिछले उदाहरणों ने भविष्य की व्यक्तिगत विशेषताओं को प्रदर्शित किया, सफलता और विफलता के मामलों को संभालना। आमतौर पर, हालांकि, दोनों सुविधाओं को बहुत अधिक नियंत्रित किया जाता है। यहाँ एक उदाहरण दिया गया है, जो एक काल्पनिक और अधिक यथार्थवादी तरीके से लिखा गया है:
object Calculator {
def calculateAndReport(a: Int, b: Int) = {
val eventualQuotient = FutureDivider divide(a, b)
eventualQuotient map {
quotient => println(s"Quotient: $quotient")
} recover {
case ex: ArithmeticException => println(s"It failed with: ${ex.getMessage}")
}
}
}
वायदा को अनुक्रमण और अनुगामी
कुछ मामलों में अलग-अलग वायदा पर मूल्यों की एक परिवर्तनीय राशि की गणना करना आवश्यक है। एक List[Future[Int]]
मान लें, लेकिन इसके बजाय एक List[Int]
को संसाधित करने की आवश्यकता है। फिर सवाल यह है कि List[Future[Int]]
इस उदाहरण को Future[List[Int]]
। इस उद्देश्य के लिए Future
साथी ऑब्जेक्ट पर sequence
विधि है।
def listOfFuture: List[Future[Int]] = List(1,2,3).map(Future(_))
def futureOfList: Future[List[Int]] = Future.sequence(listOfFuture)
सामान्य sequence
में कार्यात्मक प्रोग्रामिंग की दुनिया के भीतर एक सामान्यतः ज्ञात ऑपरेटर है जो F
और G
प्रतिबंध के साथ F[G[T]]
को G[F[T]]
।
एक वैकल्पिक ऑपरेटर है जिसे traverse
कहा traverse
, जो समान काम करता है लेकिन एक अतिरिक्त तर्क के रूप में कार्य करता है। पहचान फ़ंक्शन के साथ x => x
एक पैरामीटर के रूप में यह sequence
ऑपरेटर की तरह व्यवहार करता है।
def listOfFuture: List[Future[Int]] = List(1,2,3).map(Future(_))
def futureOfList: Future[List[Int]] = Future.traverse(listOfFuture)(x => x)
हालाँकि, अतिरिक्त तर्क दिए गए listOfFuture
अंदर प्रत्येक भविष्य के उदाहरण को संशोधित करने की अनुमति देता है। इसके अलावा, पहले तर्क को Future
सूची होने की आवश्यकता नहीं है। इसलिए उदाहरण को रूपांतरित करना संभव है:
def futureOfList: Future[List[Int]] = Future.traverse(List(1,2,3))(Future(_))
इस मामले में List(1,2,3)
को पहले तर्क के रूप में सीधे पारित किया जाता है और पहचान फ़ंक्शन x => x
को फ़ंक्शन Future(_)
साथ बदल दिया जाता है ताकि प्रत्येक Int
वैल्यू को Future
में लपेटा जा सके। इसका एक फायदा यह है कि प्रदर्शन में सुधार के लिए मध्यस्थ List[Future[Int]]
को छोड़ा जा सकता है।
कई फ्यूचर्स को मिलाएं - समझ के लिए
समझ के लिए कोड का एक ब्लॉक चलाने के लिए एक कॉम्पैक्ट तरीका है जो कई वायदा के सफल परिणाम पर निर्भर करता है।
f1, f2, f3
थ्री Future[String]
के साथ जिसमें क्रमशः one, two, three
होंगे।
val fCombined =
for {
s1 <- f1
s2 <- f2
s3 <- f3
} yield (s"$s1 - $s2 - $s3")
fCombined
एक Future[String]
जिसमें स्ट्रिंग one - two - three
एक बार सभी वायदा सफलतापूर्वक पूरा कर लेंगे।
ध्यान दें कि एक अंतर्निहित ExectionContext को यहां मान लिया गया है।
इसके अलावा, ध्यान रखें कि समझ के लिए एक फ्लैटपाइप विधि के लिए सिर्फ एक सिंथेटिक चीनी है , इसलिए शरीर के लिए भविष्य की वस्तुओं का निर्माण फ्यूचर्स द्वारा संलग्न कोड-ब्लॉकों के समवर्ती निष्पादन को समाप्त करेगा और अनुक्रमिक कोड को जन्म देगा। आप इसे उदाहरण पर देखते हैं:
val result1 = for {
first <- Future {
Thread.sleep(2000)
System.currentTimeMillis()
}
second <- Future {
Thread.sleep(1000)
System.currentTimeMillis()
}
} yield first - second
val fut1 = Future {
Thread.sleep(2000)
System.currentTimeMillis()
}
val fut2 = Future {
Thread.sleep(1000)
System.currentTimeMillis()
}
val result2 = for {
first <- fut1
second <- fut2
} yield first - second
से घिरा मूल्य result1
वस्तु हमेशा ऋणात्मक जबकि होगा result2
सकारात्मक होगा।
सामान्य रूप से समझ और yield
बारे में अधिक जानकारी के लिए , http://docs.scala-lang.org/tutorials/FAQ/yield.html देखें