原文地址:https://github.com/Microsoft/...本文介绍了Napa.js的核心概念,带领大家探索Napa.js的工作原理。关于它的由来和开发初衷,可以看这篇文章简介ZoneZone是Napa.js中的核心概念,是执行JavaScript代码的基本单位,所有涉及到多线程的内容都离不开这个概念区。一个进程可以包含多个区域,每个区域由多个JavaScriptWorker组成。区域内的所有工作人员都是相似的:它们加载相同的代码,以几乎相同的方式处理广播和执行请求,并且您无法指定在特定工作人员中执行哪些代码。不同Zone中的Worker是完全不同的:他们加载不同的代码,或者他们加载相同的代码但执行不同的策略,例如不同的堆栈大小、不同的安全策略等。应用程序将利用多个Zone来加载不同的策略。有两种类型的区域:Napa区域-由多个由Napa.js管理的JavaScriptworker组成。Napa专区中的Worker支持部分Node.jsAPINode专区——一个公开Node.js事件循环并具有完整Node.js功能的虚拟专区。这个划分可以让你使用Napazone来处理重计算事务,也可以使用Nodezone来处理IO事务。同时,Node专区也是对Napa专区无法全面支持NodeAPI的补充。以下代码创建了一个有8个工作人员的Napa区域:varnapa=require('napajs');varzone=napa.zone.create('sample-zone',{workers:8});以下代码演示了如何访问节点区域:varzone=napa.zone.node;可以在区域上执行两种类型的操作:广播-所有工作人员执行相同的代码,更改工作人员状态,并返回承诺对象。但是,我们只能通过promise的返回结果来判断执行成功与否。通常广播用于启动应用程序、预加载一些数据或修改应用程序设置。执行-在随机工作人员上执行,不更改工作人员状态,返回包含结果数据的承诺。execute通常用于做实际业务。Zone的运行采用“先进先出”的策略,但广播的优先级高于执行。下面的代码演示了使用broadcast和execute来完成一个简单的任务:functionfoo(){console.log('hi');}//这会在zone.zone.broadcast(foo.toString());//在任意worker.zone.execute(()=>{global.foo()})上执行foo函数;数据传输由于V8不适合在多个isolate之间执行JavaScript代码,因此每个isolate管理自己的内部堆栈。isolate之间传值需要编组/解组,payload的大小和对象的复杂程度决定了通信效率。所有的JavaScriptisolate都属于同一个进程,原生对象可以打包成JavaScript对象。基于此,我们尝试为Napa设计一种高效的数据传输方式。为了实现上述模式,引入了以下概念:TransportableTypesTransportabletypes是可以在worker之间自由传输的JavaScript类型。包括JavaScript基本类型:null、boolean、number、string实现了Transportable接口的对象(TypeScript类),由上述类型组成的数组或对象,以及未定义的inter-worker存储StoreAPI,用于在JavaScriptworker之间共享数据。store.set执行时,数据被编组为JSON并存储在进程的堆栈中,所有线程都可以访问该堆栈;当执行store.get时,数据被解包。下面的代码演示了如何使用store来共享数据://在node.store.set('key1',{a:1,b:"2",c:napa.memory.crtAllocator//transportablecomplextype.};//Get'key1'in另一个线程。zone.execute(()=>{varstore=global.napa.store.get('store1');console.log(store.get('key1'));});虽然方便,但是不建议在同一个事务中使用Usestore传值,因为它不仅仅是传递数据(还包括其他的东西,比如加锁)。另外,虽然有垃圾回收机制,但是开发者应该手动删除相应的key,安装执行npminstallnapajs安装,OSX系统安装后会报错,githubissue中也有同样的问题,解决办法是根据官方build文档手动build。最新版本v0.1.4已经发布修复以上问题。步骤如下:安装先决条件安装支持C++14的C++编译器:xcode-select--installInstallCMake:brewinstallcmakeInstallcmake-js:npminstall-gcmake-js通过npmnpminstall--no-fetch构建快速入门示例计算pi的π值下面是一个计算π值的例子,演示了如何使用多线程执行子任务。varnapa=require("napajs");//更改此值以控制已初始化的napaworker的数量。constNUMBER_OF_WORKERS=4;//创建一个带有number_of_workers的napazonenapaworkers.varzone=napa.zone.create('zone',{workers:NUMBER_OF_WORKERS});//使用蒙特卡罗方法估计π的值functionestimatePI(points){vari=points;内部变量=0;while(i-->0){varx=Math.random();vary=Math.random();如果((x*x)+(y*y)<=1){里面++;}}returninside/points*4;}functionrun(points,batches){varstart=Date.now();}var承诺=[];for(vari=0;i
