# 顺序

¥Sequence

序列是按特定顺序发生的多个步骤,并且一次一个。这可以用状态机来建模:

¥A sequence are a number of steps that happen in a specific order, and one at a time. This can be modeled with a state machine:

const stepMachine = createMachine({
  id: 'step',
  initial: 'one',
  states: {
    one: {
      on: { NEXT: 'two' }
    },
    two: {
      on: { NEXT: 'three', PREV: 'one' }
    },
    three: {
      type: 'final'
    }
  }
});

console.log(stepMachine.transition('one', { type: 'NEXT' }).value);
// => 'two'

在此示例中,机器处于步骤 'one''two''three',并在 'NEXT' 事件时按该顺序在这些步骤之间转换,直到到达最后一步。'PREV' 事件是可选的,允许机器转到上一步。

¥In this example, the machine is in the steps 'one', 'two', or 'three', and transitions between them in that order on the 'NEXT' event, until it reaches the last step. The 'PREV' event is optional, and allows the machine to go to a previous step.

将序列的最后一步建模为 最终状态{ type: 'final' } 使得机器更容易被另一台机器调用,或者用作更大机器的子机器,因为 onDone 可以在父机器上定义为当 序列机达到最终状态。

¥Modeling the final step of the sequence as a final state with { type: 'final' } makes it easier for the machine to be invoked by another machine, or used as a child machine of a bigger machine, since onDone can be defined on the parent machine as a transition when the sequence machine reaches its final state.

# 异步序列

¥Async Sequences

有时,许多异步(例如,基于 Promise 的)操作需要按顺序发生。这可以通过按顺序 invoking 服务进行类似的建模:

¥Sometimes, many async (e.g., Promise-based) operations need to occur in sequence. This can be modeled similarly by invoking the services in sequence:

// Returns a Promise, e.g.:
// {
//   id: 42,
//   name: 'David',
//   friends: [2, 3, 5, 7, 9] // friend IDs
// }
function getUserInfo(context) {
  return fetch(`/api/users/${context.userId}`).then((response) =>
    response.json()
  );
}

// Returns a Promise
function getUserFriends(context) {
  const { friends } = context.user;

  return Promise.all(
    friends.map((friendId) =>
      fetch(`/api/users/${friendId}/`).then((response) => response.json())
    )
  );
}

const friendsMachine = createMachine({
  id: 'friends',
  context: { userId: 42, user: undefined, friends: undefined },
  initial: 'gettingUser',
  states: {
    gettingUser: {
      invoke: {
        src: getUserInfo,
        onDone: {
          target: 'gettingFriends',
          actions: assign({
            user: (context, event) => event.data
          })
        }
      }
    },
    gettingFriends: {
      invoke: {
        src: getUserFriends,
        onDone: {
          target: 'success',
          actions: assign({
            friends: (context, event) => event.data
          })
        }
      }
    },
    success: {
      type: 'final'
    }
  }
});