Lời hứa và tương lai là những khái niệm bổ sung cho nhau. Tương lai là một giá trị sẽ được truy xuất, tốt, vào một thời điểm nào đó trong tương lai và bạn có thể làm những việc với nó khi sự kiện đó xảy ra. Do đó, nó là điểm cuối đọc hoặc ra của một phép tính - nó là thứ mà bạn lấy ra một giá trị từ đó.
Một lời hứa, bằng cách tương tự, là mặt viết của phép tính. Bạn tạo một lời hứa là nơi bạn đặt kết quả tính toán và từ lời hứa đó, bạn sẽ có được một tương lai sẽ được sử dụng để đọc kết quả được đưa vào lời hứa. Khi bạn hoàn thành một Lời hứa, dù thất bại hay thành công, bạn sẽ kích hoạt tất cả các hành vi gắn liền với Tương lai liên quan.
Đối với câu hỏi đầu tiên của bạn, làm thế nào nó có thể được cho một lời hứa p mà chúng tôi có p.future == p
. Bạn có thể tưởng tượng điều này giống như một bộ đệm một mục - một thùng chứa ban đầu trống và sau đó bạn có thể lưu trữ một giá trị sẽ trở thành nội dung của nó mãi mãi. Bây giờ, tùy thuộc vào quan điểm của bạn, đây vừa là Lời hứa vừa là Tương lai. Đó là lời hứa cho những người có ý định ghi giá trị vào bộ đệm. Đó là một tương lai cho một người nào đó chờ đợi giá trị đó được đưa vào bộ đệm.
Cụ thể, đối với API đồng thời Scala, nếu bạn xem xét đặc điểm Promise ở đây, bạn có thể thấy cách các phương thức từ đối tượng đồng hành Promise được triển khai:
object Promise {
/** Creates a promise object which can be completed with a value.
*
* @tparam T the type of the value in the promise
* @return the newly created `Promise` object
*/
def apply[T](): Promise[T] = new impl.Promise.DefaultPromise[T]()
/** Creates an already completed Promise with the specified exception.
*
* @tparam T the type of the value in the promise
* @return the newly created `Promise` object
*/
def failed[T](exception: Throwable): Promise[T] = new impl.Promise.KeptPromise[T](Failure(exception))
/** Creates an already completed Promise with the specified result.
*
* @tparam T the type of the value in the promise
* @return the newly created `Promise` object
*/
def successful[T](result: T): Promise[T] = new impl.Promise.KeptPromise[T](Success(result))
}
Bây giờ, bạn có thể tìm thấy những triển khai của các hứa hẹn, DefaultPromise và KeptPromise tại đây . Cả hai đều mở rộng một đặc điểm nhỏ cơ bản có cùng tên, nhưng nó nằm trong một gói khác:
private[concurrent] trait Promise[T] extends scala.concurrent.Promise[T] with scala.concurrent.Future[T] {
def future: this.type = this
}
Vì vậy, bạn có thể thấy ý nghĩa của chúng p.future == p
.
DefaultPromise
là bộ đệm mà tôi đã đề cập ở trên, trong khi KeptPromise
là bộ đệm với giá trị được đưa vào từ chính quá trình tạo của nó.
Về ví dụ của bạn, khối tương lai mà bạn sử dụng ở đó thực sự tạo ra một lời hứa đằng sau hậu trường. Hãy xem định nghĩa của future
in here :
def future[T](body: =>T)(implicit execctx: ExecutionContext): Future[T] = Future[T](body)
Bằng cách làm theo chuỗi phương pháp mà bạn kết thúc trong cấy ghép .
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
}
}
Vì vậy, như bạn có thể thấy, kết quả bạn nhận được từ khối nhà sản xuất của mình được đổ vào một lời hứa.
CHỈNH SỬA SAU :
Về việc sử dụng trong thế giới thực: Hầu hết thời gian bạn sẽ không giải quyết những lời hứa trực tiếp. Nếu bạn sẽ sử dụng một thư viện thực hiện tính toán không đồng bộ thì bạn sẽ chỉ làm việc với các tương lai được trả về bởi các phương thức của thư viện. Trong trường hợp này, lời hứa là do thư viện tạo ra - bạn chỉ đang làm việc với phần cuối đọc của những gì các phương pháp đó làm.
Nhưng nếu bạn cần triển khai API không đồng bộ của riêng mình, bạn sẽ phải bắt đầu làm việc với chúng. Giả sử bạn cần triển khai một ứng dụng khách HTTP không đồng bộ trên đầu trang, chẳng hạn như Netty. Sau đó, mã của bạn sẽ giống như thế này
def makeHTTPCall(request: Request): Future[Response] = {
val p = Promise[Response]
registerOnCompleteCallback(buffer => {
val response = makeResponse(buffer)
p success response
})
p.future
}