Funscript и Async.RunSynchronously

Я играл с Funscript и хотел получить какой-то результат обратно в свой рабочий процесс. Я добавил эти наивные определения (без ячейки результата) в модуль Async.

   static member RunSynchronously(workflow:Async<'T>, ?timeout:int,?cancellationToken:CancellationToken) =
      let result = ref None
      let token = defaultArg cancellationToken { Cell = None }
      let (Cont f) = workflow
      let aux = { StackCounter = ref 0; ExceptionCont = ignore; 
                  CancelledCont = ignore; CancellationToken = token }
      f { Cont = (fun v -> result :=  Some v); Aux = aux }
      let r = !result
      r.Value

   static member StartChild(computation:Async<'T>,?millisecondsTimeout:int) = 
      async { return Async.FromContinuations(fun (cont, econt,ccnt) -> cont (Async.RunSynchronously computation))           }

Который работает в этом случае

   let test =  async{  let t = async { let! r = async { return "inside" }
                                       return "Hello" } 
                       let! task = Async.StartChild t
                       let! res = task
                       return res   
                    } |> Async.RunSynchronously 

Но падает, когда спрашивается, используется "по-настоящему"

  let toto = Globals.document.createElement_img()
   toto.id <- "toto"
   Globals.document.body.appendChild(toto :> Node) |> ignore
   let test =  async{  let t = async { let! r = Async.AwaitJQueryEvent(j?toto.load)
                                       return "Hello" } 
                       let! task = Async.StartChild t
                       do toto.src <- "redundant.png"
                       let! res = task
                       return res   
                    } |> Async.RunSynchronously 

Потому что метод j? Toto.load не приостанавливает и не перезванивает, а прерывает асинхронный поток. Я думаю, это то, что нужно делать с однопоточным JavaScript.

Каково было бы реальное решение этого? Будет ли реализация supensions, как в F#, единственным способом?

1 ответ

Решение

Реализация асинхронных рабочих процессов в FunScript не использует каких-либо расширенных механизмов потоков, которые могут быть доступны в JS сегодня. Он просто запускает все в главном потоке браузера - и это также причина, почему он обеспечивает отображение только для Async.StartImmediate потому что это то, что логически соответствует этому поведению в стандартной среде выполнения F#.

Если вы хотите запустить рабочий процесс, который ожидает событие, а затем запустить его синхронно, то это не будет возможно в этой модели - и поэтому вы не можете разумно реализовать RunSynchronously это всегда будет работать (для синхронной работы вам нужно заблокировать текущий поток, но тогда вы не можете ждать событий...)

Итак, я думаю, что вам нужно каким-то образом реструктурировать свой код, чтобы он не нуждался в синхронном ожидании - возможно, также сделав вызывающий объект асинхронным.

Другие вопросы по тегам