Rohan Sircar
3 years ago
3 changed files with 168 additions and 33 deletions
@ -0,0 +1,18 @@ |
|||||
|
var i = 0; |
||||
|
|
||||
|
console.log("Starting worker") |
||||
|
onmessage = (ev) => { |
||||
|
console.log(`Worker received data ${ev.data}`) |
||||
|
const data = JSON.parse(ev.data) |
||||
|
postMessage(JSON.stringify({ data: data.data * 2 })) |
||||
|
} |
||||
|
|
||||
|
// function timedCount() {
|
||||
|
// i = i + 1;
|
||||
|
// postMessage(JSON.stringify({ data: i }));
|
||||
|
// setTimeout("timedCount()", 2000);
|
||||
|
|
||||
|
|
||||
|
// }
|
||||
|
|
||||
|
// timedCount();
|
@ -0,0 +1,122 @@ |
|||||
|
package outwatchapp.util.reactive |
||||
|
|
||||
|
import scala.concurrent.Future |
||||
|
|
||||
|
import io.circe.Decoder |
||||
|
import io.circe.Encoder |
||||
|
import io.circe.Printer |
||||
|
import io.circe.generic.JsonCodec |
||||
|
import io.circe.parser._ |
||||
|
import io.circe.syntax._ |
||||
|
import monix.bio.Task |
||||
|
import monix.execution.Ack |
||||
|
import monix.execution.Cancelable |
||||
|
import monix.reactive.Observable |
||||
|
import monix.reactive.Observer |
||||
|
import monix.reactive.OverflowStrategy |
||||
|
import outwatchapp.util.reactive.MonixProSubject |
||||
|
import org.scalajs.dom.raw.Event |
||||
|
import org.scalajs.dom.raw.MessageEvent |
||||
|
import org.scalajs.dom.{raw => sjsdr} |
||||
|
|
||||
|
class WebWorkerImpl[T <: Product: Encoder: Decoder]( |
||||
|
worker: sjsdr.Worker, |
||||
|
overflowStrategy: OverflowStrategy.Synchronous[T] |
||||
|
) { |
||||
|
|
||||
|
// private def parseFn(data: T) = { |
||||
|
// data match { |
||||
|
// case _: AnyRef => parseRef(data) |
||||
|
// case s: String => |
||||
|
// case other => |
||||
|
// println(other) |
||||
|
// Left(WebWorker.Error) |
||||
|
// } |
||||
|
// } |
||||
|
|
||||
|
// private def parseRef(data: T): Either[WebWorker.Error, T] = { |
||||
|
// data match { |
||||
|
// case s: String => decode[T](s).leftMap(_ => WebWorker.Error) |
||||
|
// case a: Int => |
||||
|
// println(a) |
||||
|
// Left(WebWorker.Error) |
||||
|
// case other => |
||||
|
// println(other) |
||||
|
// Left(WebWorker.Error) |
||||
|
// } |
||||
|
// } |
||||
|
// private def parsePrimitive(data: T): Either[WebWorker.Error, T] = { |
||||
|
// data match { |
||||
|
// case s: String => decode[T](s).leftMap(_ => WebWorker.Error) |
||||
|
// case a: Int => |
||||
|
// println(a) |
||||
|
// Left(WebWorker.Error) |
||||
|
// case other => |
||||
|
// println(other) |
||||
|
// Left(WebWorker.Error) |
||||
|
// } |
||||
|
// } |
||||
|
// println(s"Got data $a") |
||||
|
// .map(sub.onNext).left.foreach(println) |
||||
|
|
||||
|
val printer = Printer.noSpaces |
||||
|
|
||||
|
lazy val source: Task[Observable[T]] = |
||||
|
Task.deferAction(implicit s => |
||||
|
for { |
||||
|
obs <- Task( |
||||
|
Observable |
||||
|
.create[T](overflowStrategy) { sub => |
||||
|
worker.onmessage = (e: MessageEvent) => |
||||
|
e.data match { |
||||
|
case s: String => |
||||
|
decode[T](s).map(sub.onNext).left.foreach(println) |
||||
|
case other => println(other) |
||||
|
} |
||||
|
worker.onerror = (e: Event) => |
||||
|
sub.onError(new Exception(s"Error in WebSocket: $e")) |
||||
|
Cancelable(() => worker.terminate()) |
||||
|
} |
||||
|
.publish |
||||
|
.refCount |
||||
|
) |
||||
|
_ <- Task(obs.subscribe(Observer.empty)) |
||||
|
} yield obs |
||||
|
) |
||||
|
|
||||
|
lazy val sink: Task[Observer[T]] = |
||||
|
Task( |
||||
|
new Observer[T] { |
||||
|
override def onNext(elem: T): Future[Ack] = { |
||||
|
val msg = printer.print(elem.asJson) |
||||
|
worker.postMessage(msg) |
||||
|
Future.successful(Ack.Continue) |
||||
|
} |
||||
|
override def onError(ex: Throwable): Unit = println(ex) |
||||
|
override def onComplete(): Unit = () |
||||
|
} |
||||
|
) |
||||
|
|
||||
|
} |
||||
|
object WebWorker { |
||||
|
sealed trait Error |
||||
|
final case object Error extends Error |
||||
|
// val w = new sjsdr.Worker("/worker.js").asInstanceOf[Worker] |
||||
|
|
||||
|
// type MonixWebWorker[T] = MonixProSubject[T, T] |
||||
|
|
||||
|
def apply[T <: Product: Encoder: Decoder]( |
||||
|
path: String, |
||||
|
overflowStrategy: OverflowStrategy.Synchronous[T] = |
||||
|
OverflowStrategy.DropOld(50) |
||||
|
): Task[WebWorker[T]] = for { |
||||
|
worker <- Task(new sjsdr.Worker(path)) |
||||
|
impl = new WebWorkerImpl[T](worker, overflowStrategy) |
||||
|
source <- impl.source |
||||
|
sink <- impl.sink |
||||
|
} yield MonixProSubject.from(sink, source) |
||||
|
|
||||
|
} |
||||
|
|
||||
|
@JsonCodec |
||||
|
case class WorkerData(data: Long) |
Write
Preview
Loading…
Cancel
Save
Reference in new issue