
# 脚本的模块使用限制
#### 模块管理
TypeScript执行引擎没有自带模块管理，嵌入引擎时，需要开发人员手动引用。
模块管理机制类似Node.js，但因为平台是基于数据库存放脚本，没有目录与路径的概念，所以下面的module管理只是一个简化版本的Node.js模块管理，也不支持npm的整套机制。
脚本文件和模块是一一对应的，每个脚本被视为一个独立的模块。假设，有一个名称为foo的脚本：
```
import * as circle from './命名空间__circle';
console.log(`半径为 4 的圆的面积是 ${circle.area(4)}`);
```
在第一行中，foo加载circle模块。circle脚本的内容为：
```
const { PI } = Math;
exports.area = (r) => PI r *2;
exports.circumference = (r) => 2 PI r;
```
circle模块导出了area()和circumference()两个函数。通过在特殊的exports对象上，指定额外的属性，函数和对象可以被添加到模块的根部。
模块内的本地变量是私有的，因为模块被装在一个函数中。在这个例子中，变量PI是circle私有的。
![](https://support.huaweicloud.com/usermanual-astrozero/public_sys-resources/note_3.0-zh-cn.png)
在这个例子中，导入circle的时候需要在其名称上添加命名空间的字段才可以正确导入。
#### import语法
Typescript模块import语法，请参考[typescript官方网站](https://www.typescriptlang.org/docs/handbook/modules.html)。
#### 标准库模块
低代码平台中有些模块会被编译成二进制，预先加载到内存中。例如，decimal、context都是系统预置的标准库模块。
在低代码平台中，会优先加载标准库模块， 例如：
```
import * as http from 'http';
```
始终返回内置的HTTP模块，即使有同名自定义模块。如果需要返回自定义的模块，请使用相对路径语法：
```
import * as http from './http';
```
标准库模块的详细介绍，请参见[什么是脚本](https://support.huaweicloud.com/usermanual-astrozero/astrozero_05_0046.html)。
#### 扩展名
因为脚本实际上是存在数据库中的，所以脚本没有路径的概念，扩展名也没有特别的意义。
导入模块时，尽量采用不带扩展的方式。
```
import * as circle from './circle';
```
平台只允许".ts"扩展名文件存在，不允许包含".js"后缀的模块，请尽量不要使用待扩展名的导入方式。如下方式等同上面的举例，但不推荐。
```
import * as circle from './circle.ts';
```
#### 循环依赖
当循环调用模块时，一个模块可能在未完成执行时被返回。因此，需要仔细地规划模块间调用，以允许循环模块依赖在应用程序内正常工作。
例如，脚本a：
```
console.log('a 开始');
exports.done = false;
import * as b from 'b';
console.log('在 a 中，b.done = ', b.done);
exports.done = true;
console.log('a 结束');
```
脚本b：
```
console.log('b 开始');
exports.done = false;
import * as a from 'a';
console.log('在 b 中，a.done = ', a.done);
exports.done = true;
console.log('b 结束');
```
脚本main：
```
console.log('main 开始');
import * as a from 'a';
import * as b from 'b';
console.log('在 main 中，a.done = ', a.done '，b.done = ', b.done);
```
当main加载a时，a又加载b。 此时，b又会尝试去加载a。 为了防止无限的循环，会返回一个a的exports对象的未完成的副本给b模块。然后b完成加载，并将exports对象提供给a模块。当main加载这两个模块时，它们都已完成加载，因此该程序的输出会是：
```
main 开始
a 开始
b 开始
在 b 中，a.done = false
b 结束
在 a 中，b.done = true
a 结束
在 main 中，a.done=true，b.done=true
```
