原文链接:https://github.com/Microsoft/napajs/blob/master/docs/api/zone.md

Table of Contents

  • Introduction

    • Multiple workers vs Multiple zones
    • Zone types
    • Zone operations
  • API

    • create(id: string, settings: ZoneSettings = DEFAULT_SETTINGS): Zone
    • get(id: string): Zone
    • current: Zone
    • node: Zone
    • Interface ZoneSettings
      • settings.workers: number
    • Object DEFAULT_SETTINGS: ZoneSettings
    • Interface Zone
      • zone.id: string
      • zone.broadcast(code: string): Promise
      • zone.broadcast(function: (...args: any[]) => void, args?: any[]): Promise
      • zone.execute(moduleName: string, functionName: string, args?: any[], options?: CallOptions): Promise
      • zone.execute(function: (...args[]) => any, args?: any[], options?: CallOptions): Promise
    • Interface CallOptions
      • options.timeout: number
    • Interface Result
      • result.value: any
      • result.payload: string
      • result.transportContext: transport.TransportContext

概述

napajs实现了JS世界中的多线程,zone是napajs中重要的概念,它是逻辑上运行特定任务的一组对称的worker。

注意:这里的区域(zone)不同于在Dart、Angular中异步调用的上下文对象,也不同于TC39(技术委员会39)的提议。

多worker vs 多区域(zone)

zone由一个或者多个JavaScript组成,每个线程被称为一个worker。同一个zone里的worker是幂等的(对等的),也就是说在该zone里的任意一个worker上执行返回相同的结果,而且从长远来看,每一个worker的内部状态应该相同。

同一个进程中可以同时存在多个zone,每个zone载入不同的代码,呈现不同的状态或者应用不同的策略,例如堆的大小等。存在多个zone的目的是允许执行多角色的复杂任务,每个角色加载供自身使用的最少的资源。

Zone types

有两种类型的zone:

  • Napa zone - 由管理JavaScript workers(V8隔离)的Napa.js组成的zone。Napa zone可以有多个,每个zone包含多个worker。Napa zone的worker支持部分的Node.JS APIs。
  • Node zone - 一个暴露了 Node.js event loop 的虚拟 zone,它支持全部的Node.js的功能。

Zone operations

在zone上可以执行两种操作:

  1. Broadcast - 在所有的worker上执行可以改变worker状态的代码,返回一个promise对象。通过promise,我们仅能知道操作是否成功。通常,我们使用broadcast来启动应用程序、预加载对象或者改变应用设置。

  2. Execute - 在一个随机的worker上执行不会改变worker状态的程序,返回一个包含结果的promise。Execute 用于实现实际的的业务

API

create(id: string, settings: ZoneSettings): Zone

根据字符类型的id创建一个Napa zone。如果该id的zone已经存在,会抛错。ZoneSettings能设置创建的zone。

例如1:创建一个id为‘zone1’的zone,使用默认设置。

var napa = require('napajs');
var zone1 = napa.zone.create('zone1');

例如2:创建一个id为‘zone2’的zone,包含一个worker。

var zone2 = napa.zone.create('zone2', {
    workers: 1
});

get(id: string): Zone

该方法通过id获得一个zone的引用。如果该zone不存在,抛错。 例如:

var zone = napa.zone.get('zone1');

current: Zone

该方法返回当前运行的zone的引用。如果正在node下,则返回node zone。 例如:获得当前zone。

var zone = napa.zone.current;

node: Zone

该方法返回node zone的引用,等价于napa.zone.get('node') 例如:

var zone = napa.zone.node;

ZoneSettings的接口

zone的设置在创建是就会指定好。如果没有指定,则使用默认设置DEFAULT_SETTINGS。

settings.workers:number

zone中的worker的数量

DEFAULT_SETTINGS 对象

创建zone时的默认配置:

{
    workers: 2
}

Zone 接口

在Napa中,zone是执行JS和应用策略的基本概念。可以在简介中找到它的定义。通过Zone API,开发者可以在所有的worker间广播JS代码,或者在某个worker上执行一个方法。当你针对一个zone编程的时候,最好确保该zone内的所有的worker之间是幂等的(对等的),因为我们不能假设一个worker能够自己维持自身的状态。

两个主要的API集合是broadcast和execute,它们都是带有入参的异步的操作。

zone.id:string

该方法可以获得zone的id

zone.broadcast(code:string):Promise

该方法以字符串的形式向所有worker异步广播一个JS代码片段,并得到一个空的Promise句柄返回。如果存在任意一个worker执行该代码段失败,promise句柄会抛出错误。

例如:

var napa = require('napajs');
var zone = napa.zone.get('zone1');
zone.broadcast('var state = 0;')
    .then(() => {
        console.log('broadcast succeeded.');
    })
    .catch((error) => {
        console.log('broadcast failed.')
    });

zone.broadcast(function:(...args:any[])=>void,args?:any[]):Promise

该方法向所有的worker异步广播一个带有入参的匿名函数,并返回一个空的Promise句柄。如果存在任意一个worker执行该函数失败,句柄promise将会抛错。

*注意:在广播时Napa 函数不支持闭包

例如:

zone.broadcast((state) => {
        require('some-module').setModuleState(state)
    }, [{field1: 1}])
    .then(() => {
        console.log('broadcast succeeded.');
    })
    .catch((error) => {
        console.log('broadcast failed:', error)
    });

zone.execute(moduleName: string, functionName: string, args?: any[], options?: CallOptions): Promise

通过模块名和函数名在某一worker上异步执行一个函数。入参是可传递的任意JS类型。该方法返回一个名为Result的句柄。不论是不友好的代码、用户异常或者发生超时导致的错误,句柄都会被拒绝。 例如:执行‘foo’模块的‘bar’方法,传入的参数是[1,'hello',{field:1}],使用300ms的延迟。

zone.execute(
    'foo', 
    'bar', 
    [1, "hello", {field1: 1}], 
    { timeout: 300 })
    .then((result) => {
        console.log('execute succeeded:', result.value);
    })
    .catch((error) => {
        console.log('execute failed:', error);
    });

zone.execute(function: (...args: any[]) => any, args?: any[], options?: CallOptions): Promise

该方法是在任意一个worker上异步执行一个方法对象。入参是可传递的任意JS类型。该方法返回一个名为Result的句柄。不论是不友好的代码、用户异常或者发生超时导致的错误,句柄都会被拒绝。 在执行方法对象时有一些限制: 方法对象不能访问闭包里的变量 如果函数对象没有指定origin属性,则把当前文件作为origin,origin可以设置 __filename 和 __dirname。(详见transporting functions)

例如:

zone.execute((a: number, b: string, c: object) => {
        return a + b + JSON.stringify(c);
    }, [1, "hello", {field1: 1}])
    .then((result) => {
        console.log('execute succeeded:', result.value);
    })
    .catch((error) => {
        console.log('execute failed:', error);
    });

输出:

execute succeeded: 1hello{"field1":1}

下面的例子说明了当执行异步函数时如何访问 __filename:

// File: /usr/file1.js
zone.execute(() => { console.log(__filename);});

输出:

/usr/file1.js

回调操作接口

zone.execute的回调函数操作接口

options.timeout: number

超时时间为毫秒,默认值0表示没有延迟。

Result 接口

访问execute返回结果的接口

result.value:any

result.value是被zone.execute和zone.executeSync调用的函数返回的JavaScript值。Napa在不同的worker之间编组/解组可传递的值。解组发生在第一次查询result.value时。

例如:

var value = result.value;

result.payload: string

result.payload是返回值编组的载荷(以JSON的形式)。该接口使用户可以在不需要解组的地方将结果传递给它的调用者。

例如:

var payload = result.payload;

result.transportContext: transport.TransportContext

TransportContext是指要求将result.payload解组成result.value。

例如:

var napa = require('napajs');
var zone = napa.zone.create('zone1');
zone.execute(() => { return 0; }, [])
    .then((result) => {
        // Manually marshall.
        var transportContext = result.transportContext;
        var value = napa.transport.unmarshall(result.payload, result.transportContext);

        // result.value and manual unmarshall from payload are the same.
        assert.equal(value, result.value);
    });
Logo

CSDN联合极客时间,共同打造面向开发者的精品内容学习社区,助力成长!

更多推荐