Skip to content

Promise actors(Promise执行者)

Promise actors 是表示执行某些异步任务的 promise 的 actors。它们可能会返回一些输出,或者抛出一个错误。

Promise actor 功能​

功能备注
❌接收事件Promise actors 目前不接收事件。
✅发送事件Promise actors 可以向它引用的其他 actors 发送事件,例如在其 input 中提供的那些。
❌生成 actorsPromise actors 目前不能生成新的 actors。
✅输入你可以向 promise actors 提供 input。
✅输出Promise actors 可以生成 output,即 promise 的返回值。

Promise actor 逻辑​

你可以使用 fromPromise(...) actor 逻辑创建器定义 promise actor 逻辑,该创建器接受一个返回 promise 的函数,并返回可用于创建 promise actors 的 actor 逻辑。

import { fromPromise, createActor } from 'xstate';

async function getUser(id: string) {
// ...
return { id, /* other user data */ };
}

const promiseLogic = fromPromise(async () => {
const user = await getUser('123');

return user;
});

const promiseActor = createActor(promiseLogic);

promiseActor.subscribe(snapshot => {
console.log(snapshot.status, snapshot.output);
});

promiseActor.start();

// 记录 'active', undefined
// ... (过一段时间)
// 记录 'done', { id: '123', /* 其他用户数据 */ }

Promise actor 输入​

你可以通过将 input 作为第二个参数的 input 属性传递给 createActor(...) 函数来传递 input 给 promise actor。在 promise 逻辑 (fromPromise(promiseFn)) 中,你可以读取传递给 promise 函数的第一个参数的 input 属性:

import { fromPromise, createActor } from 'xstate';

const promiseLogic = fromPromise(async ({ input }) => {
const user = await getUser(input.id);

return user;
});

const promiseActor = createActor(promiseLogic, {
input: { id: '123' }
});

input 类型是从 promise 函数的第一个参数类型推断出来的。你也可以在第二个泛型参数中提供显式的 input 类型:

import { fromPromise } from 'xstate';

interface User {
name: string;
id: string;
}

const secondLogic = fromPromise(async ({ input }: { input: { id: string }}) => {
const user = await getUser(input.id); // User is inferred

return user;
});

const firstLogic = fromPromise<User, { id: string }>(async ({ input, self, /* ... */ }) => {
const user = await getUser(input.id);

return user;
});

Promise actor 输出​

要获取 promise actor 最终解析的 output,你可以订阅 promise actor 并检查快照的 status 属性。如果 status 是 'done',你可以访问快照的 output 属性以获取解析值。否则,output 将是 undefined。

import { fromPromise } from 'xstate';

const promiseLogic = fromPromise(async () => {
const user = await getUser('123');

return user;
});

const promiseActor = createActor(promiseLogic);

promiseActor.subscribe(snapshot => {
if (snapshot.status === 'done') {
console.log(snapshot.output);
// 记录 { id: '123', /* 其他用户数据 */ }
}
});

你也可以使用 toPromise(...) 将任何 actor(包括 promise actors)转换为 promise。如果你想 await actor 的 output,这将非常有用:

import { toPromise, createActor } from 'xstate';
import { somePromiseLogic } from './somePromiseLogic';

const promiseActor = createActor(somePromiseLogic);
promiseActor.start();

const output = await toPromise(promiseActor);

console.log(output);
// 记录 promise actor 解析的输出

Promise actor 错误处理​

如果 promise 逻辑中发生错误,promise actor 将会以该错误拒绝。你可以订阅 promise actor,并在错误观察者(观察者对象的 error 属性)中检查快照的 status 属性。

import { fromPromise } from 'xstate';

const promiseLogic = fromPromise(async () => {
// ...
throw new Error('Something went wrong');
});

const promiseActor = createActor(promiseLogic);
promiseActor.subscribe({
error: (error) => {
console.error(error);
// logs 'Error: Something went wrong'
}
});

promiseActor.start();

停止 promise actors​

你可以通过调用 actor 实例的 .stop() 方法来停止使用 createActor(promiseLogic) 创建的 promise actor。这将丢弃 promise 的解析或拒绝值,并处理对 promise actor 的任何订阅。

你也可以通过向其传递 signal 来中止 promise actor:

import { fromPromise, createActor } from 'xstate';

const promiseLogic = fromPromise(async ({
input,
signal
}) => {
// 如果收到信号则传递 signal 以中止获取
const data = await fetch('/some/url', { signal });

return data;
});

const promiseActor = createActor(promiseLogic);
promiseActor.start();

// ...

// 中止 promise actor
promiseActor.stop();