คำสัญญาและอนาคตเป็นแนวคิดเสริม อนาคตคือคุณค่าที่จะถูกเรียกคืนบางครั้งในอนาคตและคุณสามารถทำสิ่งต่างๆได้เมื่อเหตุการณ์นั้นเกิดขึ้น ดังนั้นจึงเป็นจุดสิ้นสุดของการคำนวณหรืออ่านหรือออก - เป็นสิ่งที่คุณดึงค่าจาก
คำสัญญาคือการเปรียบเทียบด้านการเขียนของการคำนวณ คุณสร้างคำสัญญาซึ่งเป็นสถานที่ที่คุณจะใส่ผลลัพธ์ของการคำนวณและจากคำสัญญานั้นคุณจะได้รับอนาคตที่จะใช้ในการอ่านผลลัพธ์ที่ใส่ไว้ในสัญญา เมื่อคุณทำตามคำมั่นสัญญาไม่ว่าจะด้วยความล้มเหลวหรือความสำเร็จคุณจะกระตุ้นพฤติกรรมทั้งหมดที่แนบมากับอนาคตที่เกี่ยวข้อง
เกี่ยวกับคำถามแรกของคุณ, p.future == p
วิธีที่จะสามารถเป็นไปได้ว่าสำหรับหน้าสัญญาที่เรามี คุณสามารถจินตนาการได้ว่าสิ่งนี้เป็นเหมือนบัฟเฟอร์รายการเดียว - คอนเทนเนอร์ซึ่งในตอนแรกว่างเปล่าและคุณสามารถเก็บค่าหลังคำหนึ่งซึ่งจะกลายเป็นเนื้อหาตลอดไป ตอนนี้ขึ้นอยู่กับมุมมองของคุณนี่เป็นทั้งคำสัญญาและอนาคต เป็นสัญญาสำหรับคนที่ตั้งใจจะเขียนค่าในบัฟเฟอร์ เป็นอนาคตสำหรับคนที่รอให้ค่านั้นถูกใส่ลงในบัฟเฟอร์
โดยเฉพาะอย่างยิ่งสำหรับ API ที่ทำงานร่วมกันของ Scala หากคุณดูลักษณะสัญญาในที่นี่คุณจะเห็นวิธีการใช้งานวิธีการจากวัตถุร่วมคำสัญญา:
object Promise {
def apply[T](): Promise[T] = new impl.Promise.DefaultPromise[T]()
def failed[T](exception: Throwable): Promise[T] = new impl.Promise.KeptPromise[T](Failure(exception))
def successful[T](result: T): Promise[T] = new impl.Promise.KeptPromise[T](Success(result))
}
ตอนนี้การดำเนินการของผู้สัญญา DefaultPromise และ KeptPromise สามารถพบได้ที่นี่ พวกเขาทั้งสองขยายลักษณะเล็กน้อยพื้นฐานซึ่งมีชื่อเดียวกัน แต่อยู่ในแพ็คเกจที่แตกต่างกัน:
private[concurrent] trait Promise[T] extends scala.concurrent.Promise[T] with scala.concurrent.Future[T] {
def future: this.type = this
}
คุณจะเห็นความหมายของp.future == p
มัน
DefaultPromise
คือบัฟเฟอร์ที่ฉันอ้างถึงข้างต้นในขณะที่KeptPromise
เป็นบัฟเฟอร์ที่มีค่าที่นำมาจากการสร้างมาก
เกี่ยวกับตัวอย่างของคุณบล็อกในอนาคตที่คุณใช้ที่นั่นสร้างสัญญาเบื้องหลัง ดู Let 's ที่นิยามของfuture
ในที่นี่ :
def future[T](body: =>T)(implicit execctx: ExecutionContext): Future[T] = Future[T](body)
โดยทำตามห่วงโซ่ของวิธีการที่คุณจะสิ้นสุดในimpl.Future :
private[concurrent] object Future {
class PromiseCompletingRunnable[T](body: => T) extends Runnable {
val promise = new Promise.DefaultPromise[T]()
override def run() = {
promise complete {
try Success(body) catch { case NonFatal(e) => Failure(e) }
}
}
}
def apply[T](body: =>T)(implicit executor: ExecutionContext): scala.concurrent.Future[T] = {
val runnable = new PromiseCompletingRunnable(body)
executor.execute(runnable)
runnable.promise.future
}
}
ดังที่คุณเห็นผลลัพธ์ที่คุณได้รับจากบล็อกโปรดิวเซอร์ของคุณถูกเทลงในสัญญา
แก้ไขภายหลัง :
เกี่ยวกับการใช้งานในโลกแห่งความเป็นจริง: ส่วนใหญ่แล้วคุณจะไม่จัดการกับคำสัญญาโดยตรง หากคุณใช้ไลบรารีที่ทำการคำนวณแบบอะซิงโครนัสคุณก็จะทำงานกับฟิวเจอร์สที่ส่งคืนโดยวิธีการของไลบรารี ในกรณีนี้คำสัญญาเป็นสิ่งที่สร้างขึ้นโดยไลบรารี - คุณกำลังดำเนินการอ่านให้จบว่าวิธีการเหล่านั้นทำอะไร
แต่ถ้าคุณต้องการใช้ API แบบอะซิงโครนัสของคุณเองคุณจะต้องเริ่มทำงานกับ API เหล่านี้ สมมติว่าคุณต้องติดตั้งไคลเอนต์ async HTTP ที่ด้านบนสมมติว่า Netty จากนั้นรหัสของคุณจะมีลักษณะเช่นนี้
def makeHTTPCall(request: Request): Future[Response] = {
val p = Promise[Response]
registerOnCompleteCallback(buffer => {
val response = makeResponse(buffer)
p success response
})
p.future
}