.vb.net 执行js方法_Deno的执行机制

上一篇主要围绕Deno核心模块中安全沙箱机制与依赖引入管理进行了讲解。本篇文章我们将对Deno的执行机制进行一些介绍。

Deno的架构

先说说Deno的架构吧,这是官网的核心架构图

73f30d43f857e0b234f83848e45186a1.png

不过这张图很久没更新了,有些实现有些变化。主要变化就是libdeno已经替换成rusty_v8,js可以直接和rust进行交互了,使用rust就可以完成功能开发。

Deno里面js与rust的交互都会通过Deno.core.send和Deno.core.recv这两个方法,send发起同步任务,recv用来触发异步回调。

Tokio

Tokio是一个事件驱动的非阻塞I/O平台,用于使用Rust编程语言编写异步应用程序,相当于node中libuv。Tokio中的异步模型,是基于future实现的,熟悉Rust语言的应该很了解。基于我们熟悉的promise,简单对比一下,future的基本特征:

future特征:trait SimpleFuture {    type Output;    fn poll(&mut self, wake: fn()) -> Poll<Self::Output>;} enum Poll {    Ready(T),    Pending,}

js中的promise状态转移靠的是push,它本身就是一个事件源,能够主动去改变自身状态,我们在then函数中注册的回调,会自动在下一个微任务队列中执行;

而future靠的是poll,需要一个excutor去轮询获取其状态,也就是说excutor会在适当的时候执行future的poll方法,当返回状态为Poll::Pending也就意味需要excutor等待进行下一次轮询,当返回Poll::Ready也就是意味future已经完成,然后根据返回的值去判断是否出错,去执行下一步代码逻辑。

当然了,excutor不会不间断地去轮询,所以future的poll方法里面是可以设置一个waker(唤醒任务),去通知excutor什么时候该来轮询的。

86c27f6514978ac22a6222837b14a1a4.png

Deno程序是怎么执行的

入口函数:cli/main.rs的main方法,主要干了两件事:

  1. 解析命令行参数然后创建对应的future(任务)

  2. 启动Tokio执行future(任务)

894f794607013990e25f8447673b2fa8.png

通过代码可以看出,关键的步骤就是Run对应的逻辑,也就是run_command方法。

f2bf21a279b990ee90a4156119021b60.png

核心逻辑就是Deno会创建一个MainWorker,就是我们的主进程,然后是四个关键步骤:执行用户逻辑代码->触发load事件->事件循环->触发unload事件

JS与Rust交互

代码路径:core/core.js

deno里面JS与Rust的交互只能通过send和recv这两个方法

send会根据opId去调用对应的rust方法,同步方法会直接返回,异步的话,需要通过recv去获取异步结果

Object.assign(window.Deno.core, {    jsonOpAsync,    jsonOpSync,    setAsyncHandler,dispatch: send,    ops,    close,sharedQueue: {},    ...  })

其中ops很关键,它是一个系统操作映射表,将操作和一个唯一的id进行关联,是JS和Rust之间沟通的桥梁。

整个core.js就是给Window.Deno.core定义这些api方法,Deno中触发任务的代码如下:

//同步Deno.core.dispatch(opId, scratchBytes, ...zeroCopy);//异步Deno.core.setAsyncHandler(opId,cb)Deno.core.dispatch(opId, scratchBytes, ...zeroCopy);

接下来,我们通过关键代码,看下基本流程是什么样的。

fc76ff954a7afcfc585ddc9ceb189c0b.png

4f98294651786945c117e420bfa173f2.png

通过setAsyncHandler设定的回调函数,会进行初始化,回调函数会存储到全局的handles表里。初始化函数里设置recv的回调函数,供Tokio异步任务完成后触发。handleAsyncMsgFromRust函数则会从全局的回调队列中取出队首任务,根据opId去执行对应的handler。

核心代码实现:

5e1c8deba33c48901ac8ee4b5ddffad1.png

最后来到core/bingding.rs的initialize_context,在这里是deno初始化核心方法的地方(都是挂在Deno.core这个对象下),send和recv也是在这里注入到JS中的。

4e3ee086a123cecf30c531df57ee0108.png

用一张流程图,将上述的片段串一下:

0b5fd8370ae607c829846059fb733151.png

总结

本期我们主要讲了deno的部分实现与执行机制,之后的文章我们会在deno的生态及工程化等方面继续进行讲解,敬请期待。

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值