2016-07-13 14 views
-1

Wir könnten js_of_ocaml verwenden, um eine JS-Funktion zu umbrechen und sie somit innerhalb von OCaml aufzurufen. Ich kann kein funktionierendes Beispiel erstellen, wenn die JS-Funktion asynchron ist (dh Versprechen enthält und Zeit braucht).Ist es möglich, eine asynchrone JS-Funktion zu umbrechen und sie in OCaml zu verwenden?

Die asynchrone JS-Funktion JSfun möchte ich wie folgt umbrechen. Die Variable x wird nach 2 Sekunden auf "here" gesetzt. Dies ist der Wert, den ich zurückgeben möchte.

function JSfun() { 
    var x = "before"; 
    return new Promise(function(resolve, reject) { 
    setTimeout(function() { 
     append("inside setTimeout"); 
     x = "here"; 
     resolve(x); 
    }, 2000); 
    }) 
} 

Wir erfolgreich JSfun in JS nennen könnte und bekommen "runJS here" wie erwartet:

function runJS() { 
    JSfun().then(function(res) { 
    append("runJS " + res) 
    }) 
} 

Es ist jedoch schwer, diese Verkettung von OCaml zu imitieren. Einzuwickeln JSfun in OCaml, so scheint es, dass wir verwenden:

Js.Unsafe.global##.OCamlcall := Js.wrap_callback 
    (fun _ -> 
     let m = Js.Unsafe.fun_call (Js.Unsafe.js_expr "JSfun") [||] in 
     Js.string ((Js.to_string m)^" Via OCaml") 
    ); 

Und ich habe keine andere Idee, als wie dieser Aufruf:

function runOCaml() { 
    var res = OCamlcall("abc"); 
    append(res); 
} 

Es überrascht nicht, es funktioniert nicht: wir tun siehe "inside setTimeout" gedruckt, was beweist, JSfun wurde aufgerufen, aber der Rückgabewert war nicht da.

Hier ist die jsfiddle. Ich mache auch ein funktionierendes Beispiel für das Wrapping der synchronen JS-Funktion. In OCaml ist die Verpackung:

Js.Unsafe.global##.OCamlcallSync := Js.wrap_callback 
    (fun _ -> 
     let m = Js.Unsafe.fun_call (Js.Unsafe.js_expr "JSfunSync") [||] in 
     Js.string ((Js.to_string m)^" Via OCaml") 
    ); 

Hat also jemand eine Lösung, eine Idee oder einen Workaround?

Antwort

1

Wenn Ihre js-Funktion asynchron ist, sollte Ihr OCaml-Gegenstück auch async sein, d. H. Es sollte Lwt oder Async verwenden. Also, für Lwt würden Sie wahrscheinlich Lwt.task verwenden, um schlafende Thread und Wakeer zu erstellen, dann Callback mit Wakner an Promises '.then Methode übergeben und schlafende Thread von Ihrer Funktion zurückgeben.

Der Code würde wie folgt aussehen (einige Arten wahrscheinlich zu allgemein sind):

class type promise = 
    object 
    method then_ : ('a -> 'b) callback -> 'b meth 
    end 

let ocamlcall() = 
    let t, w = Lwt.task() in 
    let wakeup = Js.wrap_callback (fun r -> Lwt.wakeup t r) in 
    let (promise : promise Js.t) = Js.Unsafe.fun_call jsfunc [||] in 
    let() = ignore @@ promise##then_ wakeup in 
    t 

Anmerkung: Ich habe diesen Code nicht getestet, aber es sollte Ihre allgemeine Idee geben, wie mit Asynchron-js Funktionen zur Interaktion .

Sie können auch überprüfen, wie jsoo selbst mit jsonp arbeitet, zum Beispiel: https://github.com/ocsigen/js_of_ocaml/blob/master/lib/jsonp.ml