ClientContext

ClientContext

Base class to extend in order to implement a new Context.

In the soundworks paradigm, a client has a "role" (e.g. player, controller) see Client#role) and can be in different "contexts" (e.g. different part of the experience such as sections of a music piece, etc.). This class provides a simple and unified way to model these reccuring aspects of an application.

You can also think of a Context as a state of a state machine from which a client can enter() or exit() (be aware that soundworks does not provide an implementation for the state machine).

Optionally, a Context can also have a server-side counterpart to perform some logic (e.g. updating some global shared state) when a client enters or exits the context. In such case, soundworks guarantees that the server-side logic is executed before the enter() and exit() promises are fulfilled.

import { Client, ClientContext } from '@soundworks/core/index.js'

const client = new Client(config);

class MyContext extends ClientContext {
  async enter() {
    await super.enter();
    console.log(`client ${this.client.id} entered my context`);
  }

  async exit() {
    await super.exit();
    console.log(`client ${this.client.id} exited my context`);
  }
}
const myContext = new MyContext(client);

await client.start();
await myContext.enter();

await new Promise(resolve => setTimeout(resolve, 2000));
await myContext.exit();

Constructor

new ClientContext(client)

Source:
Parameters:
Name Type Description
client Client

The soundworks client instance.

Throws:

Will throw if the first argument is not a soundworks client instance.

Members

client :Client

Description:
  • The soundworks client instance.

Source:

The soundworks client instance.

Type:

(readonly) name :string

Description:
  • Optionnal user-defined name of the context (defaults to the class name).

    The context manager will match the client-side and server-side contexts based on this name. If the ServerContextManager don't find a corresponding user-defined context with the same name, it will use a default (noop) context.

Source:

Optionnal user-defined name of the context (defaults to the class name).

The context manager will match the client-side and server-side contexts based on this name. If the ServerContextManager don't find a corresponding user-defined context with the same name, it will use a default (noop) context.

Type:
  • string
Example
// server-side and client-side contexts are matched based on their respective `name`
class MyContext extends Context {
  get name() {
    return 'my-user-defined-context-name';
  }
}

status :'idle'|'inited'|'started'|'errored'

Description:
  • Status of the context.

Source:

Status of the context.

Type:
  • 'idle' | 'inited' | 'started' | 'errored'

Methods

(async) enter() → {Promise.<void>}

Description:
  • Enter the context. Implement this method to define the logic that should be done (e.g. creating a shared state, etc.) when the context is entered.

    If a server-side part of the context is defined (i.e. a context with the same ClientContext#name), the corresponding server-side enter() method will be executed before the returned Promise is fulfilled.

    If the context has not been started yet, the start method is implicitely executed.

Source:
Example
class MyContext extends Context {
  async enter() {
    await super.enter();
    this.state = await this.client.stateManager.create('my-context-state');
  }

  async exit() {
    await super.exit();
    await this.state.delete();
  }
}
Returns:
  • Promise that resolves when the context is entered.
Type
Promise.<void>

(async) exit() → {Promise.<void>}

Description:
  • Exit the context. Implement this method to define the logic that should be done (e.g. delete a shared state, etc.) when the context is exited.

    If a server-side part of the context is defined (i.e. a context with the same ClientContext#name), the corresponding server-side exit() method will be executed before the returned Promise is fulfilled.

Source:
Example
class MyContext extends Context {
  async enter() {
    await super.enter();
    this.state = await this.client.stateManager.create('my-context-state');
  }

  async exit() {
    await super.exit();
    await this.state.delete();
  }
}
Returns:
  • Promise that resolves when the context is exited.
Type
Promise.<void>

(async) start()

Description:
  • Start the context. This method is lazilly called when the client enters the context for the first time (cf. ${ClientContext#enter}). If you know some some heavy and/or potentially long job has to be done when starting the context (e.g. call to a web service) it may be a good practice to call it explicitely.

    This method should be implemented to perform operations that are valid for the whole lifetime of the context, regardless the client enters or exits the context.

Source:
Example
import { Context } from '@soundworks/core/client.js';

class MyContext extends Context {
  async start() {
    await super.start();
    await this.doSomeLongJob();
  }
}

// Instantiate the context
const myContext = new Context(client);
// manually start the context to perform the long operation before the client
// enters the context.
await myContext.start();

(async) stop()

Description:
  • Stop the context. This method is automatically called when await client.stop() is called. It should be used to cleanup context wise operations made in start() (e.g. destroy the reusable audio graph).

    WARNING: this method should never be called manually.

Source: