# task

## 功能

创建轻量后台任务。`task(fn, ...args)` 会立即返回 `Task` 对象，任务函数在后台独立 VM 中执行；主流程可通过 `await()` 阻塞等待结果，通过 `done()` 查询完成状态，通过 `result()` 非阻塞读取结果，也可以通过 `on_done(fn)` 在长期 VM 事件循环中注册完成回调。

后台任务采用快照传值，不共享主 VM 的数组、对象、闭包或全局变量引用。显式参数、闭包捕获和可能访问的全局变量都会在创建任务时快照。

## 语法

```bt
t = task(fn(value) {
    return value + 1
}, 6)

value = t.await()
done = t.done()
result = t.result()
```

## 参数

| 参数 | 类型 | 必填 | 默认值 | 说明 |
| ------ | ------ | ------ | ------ | ------ |
| fn | Fn | 是 | 无 | 后台任务入口函数，只执行一次。 |
| ...args | 任意可快照值 | 否 | 无 | 传给任务入口函数的显式参数，按创建任务时快照。 |

## 返回值

| 类型 | 说明 |
| ------ | ------ |
| Task | 后台任务对象，包含 await、done、result、on_done 方法。 |

## Task 方法

| 方法 | 返回值 | 说明 |
| ------ | ------ | ------ |
| await() | 任意值 | 阻塞等待任务完成；成功返回结果；任务内部 throw 时重新抛出；普通运行时错误按运行时错误返回。 |
| done() | Bool | 非阻塞判断任务是否完成。 |
| result() | 任意值 / Empty | 非阻塞读取结果；未完成返回 empty；成功返回结果；任务内部 throw 时重新抛出。 |
| on_done(fn) | Task | 注册完成回调并返回当前 Task，方便链式调用。 |

## on_done 回调

```bt
t.on_done(fn(result, err, status) {
    if status != 'success' {
        return empty
    }

    // 输出：123
    print result
})
```

| 参数 | 类型 | 说明 |
| ------ | ------ | ------ |
| result | 任意值 / Empty | 任务成功时为返回值；失败或 throw 时为 empty。 |
| err | 任意值 / String / Empty | 任务 throw 时为抛出的值；普通失败时为错误文本；成功时为 empty。 |
| status | String | `success`、`throw` 或 `failed`。 |

`on_done()` 回调在注册它的 VM 线程执行，不会在后台任务线程直接执行。CLI 脚本和桌面长期 VM 会在主流程结束后的事件边界分发回调；Web 请求 VM 生命周期短，不能注册 `on_done()`。

## 可快照类型

| 类型 | 说明 |
| ------ | ------ |
| Null | 保留显式空值。 |
| Empty | 保留缺失值；序列化到 JSON 时仍按 JSON null 输出。 |
| Int / Float / Bool / String | 按值复制。 |
| Array / Object | 递归深快照，后台 VM 和主 VM 不共享可变引用。 |

函数值、类实例、正则对象、日期对象、文件句柄、数据库连接、网络连接、设备句柄、进程句柄和原生对象不能进入任务快照，也不能作为任务结果返回。

## 示例

```bt
t = task(fn(value) {
    sleep(100)
    return value + 1
}, 122)

value = t.await()

// 输出：123
print value
```

```bt
t = task(fn() {
    sleep(100)
    return 7
})

pending = t.result()
sleep(200)
value = t.result()

// 输出：empty
print pending

// 输出：7
print value
```

```bt
data = {count: 1}

t = task(fn(item) {
    item.count = 9
    return item.count
}, data)

data.count = 2
result = t.await()

// 输出：2
print data.count

// 输出：9
print result
```

```bt
task(fn() {
    return 123
}).on_done(fn(result, err, status) {
    if status == 'success' {
        // 输出：123
        print result
    }
})
```

## 注意事项

- `task(fn, ...args)` 只创建轻量后台任务，不引入 async fn、await 关键字、Promise、channel 或共享可变状态。
- 任务函数在独立 VM 中执行，显式参数、捕获变量和全局变量按创建任务时快照。
- `await()`、`task_all()` 和 `task_race()` 会阻塞当前执行流；Web 请求上下文中会直接拒绝这些同步等待方法。
- `Task.on_done()` 只能用于 CLI 常驻脚本和桌面长期 VM，不能用于 Web 请求上下文。
- Web 请求中允许提交 `task(fn, ...args)`，但不能在请求内注册回调或等待完成；完整规则见：[Web 阻塞 API 策略](/docs/web/io-policy)。
- 后台任务队列、线程数、快照大小、完成订阅和回调表都有上限；超过上限会返回运行时错误。
- 可通过环境变量 `BT_TASK_WORKERS` 和 `BT_TASK_QUEUE` 调整后台任务线程数和队列长度，实际值仍会被运行时安全上限约束。
