> ## Documentation Index
> Fetch the complete documentation index at: https://docs.youka.io/llms.txt
> Use this file to discover all available pages before exploring further.

# 任务

> 检查任务并等待异步操作完成

在 Youka 中，每个异步操作最终都会以任务的形式运行，但目前 SDK 的主要接口会返回操作句柄，而不是原始任务 ID。大多数调用方应该使用 `client.projects.wait(...)` 或 `client.exports.wait(...)`，只有在需要进行底层任务检查时才使用 `client.tasks.*`。

## `client.tasks.get(taskId, options?)`

按 ID 获取任务的当前状态。

```ts theme={null}
const task = await client.tasks.get("tsk_abc123");
console.log(task.status, task.type);
```

### 任务状态

| 状态            | 终态？ | 含义             |
| ------------- | --- | -------------- |
| `created`     | 否   | 任务已创建，但尚未进入队列。 |
| `queued`      | 否   | 任务正在等待运行。      |
| `in-progress` | 否   | 任务正在执行中。       |
| `completed`   | 是   | 任务已成功完成。       |
| `finalized`   | 是   | 任务已完成，且后处理已结束。 |
| `failed`      | 是   | 任务因错误而失败。      |
| `cancelled`   | 是   | 任务已被取消。        |
| `timed-out`   | 是   | 任务已达到时间限制。     |

## `client.tasks.wait(taskId, options?)`

轮询任务，直到它进入终态。成功时返回最终任务；失败时抛出 `YoukaTaskError`。

```ts theme={null}
const task = await client.tasks.wait("tsk_abc123", {
  pollIntervalMs: 3_000,
  signal: abortController.signal,
});
```

### 选项

<ParamField path="pollIntervalMs" type="number">
  两次轮询之间的毫秒数。默认为 `2000`。
</ParamField>

<ParamField path="signal" type="AbortSignal">
  中止等待。进行中的请求以及任何尚未执行的延迟都会立即取消。
</ParamField>

### 错误

当任务以 `failed`、`cancelled` 或 `timed-out` 结束时，`client.tasks.wait(...)` 会抛出 `YoukaTaskError`：

```ts theme={null}
import { YoukaTaskError } from "@youka/sdk";

try {
  await client.tasks.wait("tsk_abc123");
} catch (error) {
  if (error instanceof YoukaTaskError) {
    console.error(error.code); // TASK_FAILED | TASK_CANCELLED | TASK_TIMED_OUT
    console.error(error.task); // Full RestTask payload
  }
  throw error;
}
```

## `client.projects.wait(operation, options?)`

等待项目范围内的操作完成，然后重新获取项目。返回操作句柄、进入终态的任务以及更新后的项目。

```ts theme={null}
const operation = await client.projects.create({
  source: { type: "path", path: "./song.mp3" },
});

const { project, task } = await client.projects.wait(operation, {
  pollIntervalMs: 2_500,
});

console.log("Project ready:", project.id);
console.log("Task finished in state:", task.status);
```

<ParamField path="operation" type="ProjectOperation" required>
  通常是 `client.projects.create(...)`、`client.projects.separateStems(...)` 或 `client.projects.syncLyrics(...)` 的返回结果。
</ParamField>

## `client.exports.wait(operationOrId, options?)`

等待云端导出进入终态。可传入 `client.exports.create(...)` 返回的 `ExportOperation`，或一个 `exportId` 字符串。

```ts theme={null}
const operation = await client.exports.create("prj_abc123", {
  resolution: "1080p",
  quality: "high",
});

const finalized = await client.exports.wait(operation, {
  pollIntervalMs: 3_000,
});

console.log(finalized.status, finalized.url);
```

## 取消

传入 `AbortSignal` 以取消长时间等待：

```ts theme={null}
const controller = new AbortController();

setTimeout(() => controller.abort(), 60_000);

try {
  await client.projects.wait(operation, { signal: controller.signal });
} catch (error) {
  if (error instanceof Error && error.name === "AbortError") {
    console.log("Wait cancelled after 60s");
  } else {
    throw error;
  }
}
```

同一个 signal 也会取消底层的任务或导出轮询请求。

## 下一步

* [错误](/zh/sdk/errors) — 处理 `YoukaTaskError` 和可重试错误
* [导出](/zh/sdk/exports) — 等待导出完成
* [API async jobs](/zh/api/async-jobs) — 在原始 HTTP 中使用相同模式
