OCaml / Node.JS上的Lwt.async和Lwt_main.run之间有什么区别?

我正在试验js_of_ocamljs_of_ocaml 如您所知,node.js大量使用callback来实现asynchronous请求,而不引入显式线程。

在OCaml中,我们有一个非常好的线程库Lwt,它有一个非常有用的语法扩展。 我编写了一个绑定到某个节点库(AWS S3客户端)的原型,并添加了一个lwt-ish图层来隐藏callback。

 open Lwt.Infix open Printf open Js let require_module s = Js.Unsafe.fun_call (Js.Unsafe.js_expr "require") [|Js.Unsafe.inject (Js.string s)|] let _js_aws = require_module "aws-sdk" let array_to_list a = let ax = ref [] in begin for i = 0 to a##.length - 1 do Optdef.iter (array_get ai) (fun x -> ax := x :: !ax) done; !ax end class type error = object end class type bucket = object method _Name : js_string t readonly_prop method _CreationDate : date t readonly_prop end class type listBucketsData = object method _Buckets : (bucket t) js_array t readonly_prop end class type s3 = object method listBuckets : (error -> listBucketsData t -> unit) callback -> unit meth end let createClient : unit -> s3 t = fun () -> let constr_s3 = _js_aws##.S3 in new%js constr_s3 () module S3 : sig type t val create : unit -> t val list_buckets : t -> (string * string) list Lwt.t end = struct type t = s3 Js.t let create () = createClient () let list_buckets client = let cell_of_bucket_data data = ((to_string data##._Name), (to_string data##._CreationDate##toString)) in let mvar = Lwt_mvar.create_empty () in let callback error buckets = let p () = if true then Lwt_mvar.put mvar (`Ok(List.map cell_of_bucket_data @@ array_to_list buckets##._Buckets)) else Lwt_mvar.put mvar (`Error("Ups")) in Lwt.async p in begin client##listBuckets (wrap_callback callback); Lwt.bind (Lwt_mvar.take mvar) (function | `Ok(whatever) -> Lwt.return whatever | `Error(mesg) -> Lwt.fail_with mesg) end end let () = let s3 = S3.create() in let dump lst = Lwt_list.iter_s (fun (name, creation_date) -> printf "%32s\t%s\n" name creation_date; Lwt.return_unit) lst in let t () = S3.list_buckets s3 >>= dump in begin Lwt.async t end 

由于没有绑定到node.js的Lwt_main ,我不得不运行我的代码与Lwt.async 。 运行代码与Lwt.async而不是Lwt_main.run有什么Lwt_main.run – 后者在node.js中不存在? 是保证程序将等到asynchronous线程完成退出之前,或者这是一个幸运,但我的代码的随机行为?

Lwt_main.run函数recursion地轮询它监督其执行的线程。 在每次迭代中,如果此线程仍在运行,则调度程序使用一个引擎(来自Lwt_engine )通过select或同步事件来执行等待I / O的线程。

在Node.JS中翻译这个的自然方法是使用process.nextTick方法,该方法依赖于Node.JS自己的调度程序。 在这种情况下实现Lwt_main.run函数可以像下面这样简单:

 let next_tick (callback : unit -> unit) = Js.Unsafe.(fun_call (js_expr "process.nextTick") [| inject (Js.wrap_callback callback) |]) let rec run t = Lwt.wakeup_paused (); match Lwt.poll t with | Some x -> x | None -> next_tick (fun () -> run t) 

这个函数只运行unit Lwt.ttypes的线程,但这是程序的主要情况。 可以使用Lwt_mvar.t来计算任意值进行通信。

也可以扩展这个例子来支持所有types的钩子,就像原来的Lwt_main.run实现一样。

Interesting Posts