खोज…


भविष्य बनाना

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 देखें



Modified text is an extract of the original Stack Overflow Documentation
के तहत लाइसेंस प्राप्त है CC BY-SA 3.0
से संबद्ध नहीं है Stack Overflow