首页
学习
活动
专区
圈层
工具
发布
社区首页 >问答首页 >Lwt.async和Lwt_main.run在OCaml/Node.JS上有什么不同?

Lwt.async和Lwt_main.run在OCaml/Node.JS上有什么不同?
EN

Stack Overflow用户
提问于 2016-01-21 16:40:51
回答 1查看 921关注 0票数 3

我正在用js_of_ocaml和node.js做实验。如您所知,node.js广泛使用回调来实现异步请求,而不引入显式线程。

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

代码语言:javascript
复制
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 a i) (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没有绑定到node.js,所以我不得不使用Lwt.async运行代码。使用Lwt.async而不是Lwt_main.run运行代码有什么区别--后者并不存在于node.js中?它是否保证程序在退出前等待异步线程完成,或者这是我的代码的幸运但随机的行为?

EN

回答 1

Stack Overflow用户

回答已采纳

发布于 2016-01-24 12:17:48

Lwt_main.run函数递归地轮询它监视其执行的线程。在每次迭代时,如果该线程仍在运行,调度程序将使用一个引擎(来自Lwt_engine)通过选择或同步事件来执行等待I/O的线程。

在Node.JS中转换这一点的自然方法是使用process.nextTick方法,它依赖于Node.JS自己的调度程序。在这种情况下实现Lwt_main.run函数可以非常简单,如下所示:

代码语言:javascript
复制
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.t类型的线程,但这是程序的主要情况。可以使用Lwt_mvar.t来计算任意值以进行通信。

还可以扩展此示例以支持所有类型的钩子,如原始Lwt_main.run实现中的那样。

票数 1
EN
页面原文内容由Stack Overflow提供。腾讯云小微IT领域专用引擎提供翻译支持
原文链接:

https://stackoverflow.com/questions/34929382

复制
相关文章

相似问题

领券
问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档