2017-06-03 43 views
1

請考慮運行在瀏覽器中的一個scala.js應用程序,它由一個主程序和一個web worker組成。如何在期貨中包裝Web Worker響應消息?

主線程通過傳遞包含方法名稱和調用它們所需參數的消息,將長時間運行的操作委託給Web Worker。工作人員以響應消息的形式將方法返回值傳遞迴主線程。

簡單來說,這個程序會抽象出web worker的消息傳遞,這樣主線程中的代碼就可以在工作線程中以慣用和異步的Scala語法調用方法。

因爲網絡工作人員不會以任何方式將消息與其響應關聯起來,所以抽象依賴於註冊中心,一箇中介對象,該中介對象控制每個跨上下文方法調用以將調用與結果相關聯。這個單例還可以綁定回調函數,但是有沒有一種方法可以通過期貨而不是回調來實現?

如何在此註冊表上構建一個抽象,允許程序員將它與Scala中的標準異步編程結構一起使用:期貨和承諾?

我應該如何編寫這個功能,以便scala程序員能夠以規範的方式與它交互?例如:

// long running method in the web worker 
val f: Future[String] = Registry.ultimateQuestion(42) // async 

f onSuccess { case q => println("The ultimate question is: " + q) } 

我不熟悉期貨和承諾,但看起來他們通常在某些執行塊終止時完成。在這種情況下,收到網絡工作者的迴應意味着未來的完成。有沒有辦法編寫一個將其完成狀態委託給外部過程的自定義未來?是否有另一種方式將網絡工作者的迴應信息與未來的狀態聯繫起來?

可以/我應該延長未來的特質嗎?這可能在Scala.js中嗎?我應該延伸一個具體的課程嗎?有沒有其他的方式來封裝這些跨現有的Web工作方法調用現有的異步Scala功能?

謝謝您的考慮。

回答

2

嗯。只是在這裏吐了口水(我還沒有使用過工人),但似乎將請求與Future相關聯在您正在使用的單線程JavaScript世界中相當容易。

這是一個假設設計。假設對工作人員的每個請求/響應都自動包裝在信封中;信封包含一個RequestId。因此,發送端看起來像(這是僞代碼,但實際ISH):

def sendRequest[R](msg:Message):Future[R] = { 
    val promise = Promise[R] 
    val id = nextRequestId() 
    val envelope = Envelope(id, msg) 
    register(id, promise) 
    sendToWorker(envelope) 
    promise.future 
} 

工作進程味精,包裝在另一個信封結果,結果被處理回主線程與是這樣的:

def handleResult(resultEnv:Envelope):Unit = { 
    val promise = findRegistered(resultEnv.id) 
    val result = resultEnv.msg 
    promise.success(result) 
} 

這需要一些填充,以及有關類型,如R應該是什麼樣的一些想法,但那種輪廓可能會工作體面的好。如果這是JVM,你不得不擔心各種競爭條件,但在單線程的JS世界中,它可能就像爲請求ID使用自動遞增整數一樣簡單,並存儲Promise ...

+0

哦!所以Promise允許程序員通過調用一個setter來確定何時履行承諾?如果這樣做,我應該重新命名這個問題:「我不知道什麼是承諾!」謝謝,賈斯汀!:) –

+0

正確。承諾和期貨基本上是一脈相承的 - 你可以將承諾視爲「生產者」一方,將未來視爲「消費者」一方。上面說明的模式 - 創建Promise,返回promise.future,當事情真的完成時,調用promise.success()的值 - 幾乎是將「callback-y」API連接到線程的標準方式期貨。 –