# Dispatch Commands

Positron's IPC system is fully event-driven. Because of this, synchronous return values are not possible across the IPC bridge. To support request/response style APIs, Positron wraps IPC events in a `Promise`.

{% code lineNumbers="true" %}

```js
  const result = await mainWindow.request(
    "canGoBack",
    `canGoBack-reply-${this.id}`
  );
```

{% endcode %}

### Why This Exists

IPC communication is asynchronous by nature. This means code like:

{% code lineNumbers="true" %}

```js
const result = sendCommand("canGoBack");
```

{% endcode %}

cannot work directly because the renderer response arrives later as a separate event. The `request()` helper abstracts this complexity and provides a clean Promise-based API.

### Important Notes

#### Unique Reply Channels

Reply channels should be unique per window or request:

{% code lineNumbers="true" %}

```js
`canGoBack-reply-${this.id}`
```

{% endcode %}

This prevents collisions between multiple renderer instances.

### Recommended Pattern

#### For APIs that expect a return value:

> **Best Practice:** Always include the `window.id` in your reply channel string and ensure it contains the phrase `-reply-` or `-result-`. Positron’s internal router automatically intercepts native events containing `-reply-` or `-result-` and routes them directly to IPC listeners.

{% code lineNumbers="true" %}

```javascript
const { Window } = require('positron.js');

const win = new Window();

win.on('ready', async () => {
    try {
        // We define a unique reply channel for this request.
        const replyChannel = `my-ext-reply-${win.id}`;
        
        // request() resolves when the native layer responds on 'my-ext-reply-X'
        const response = await win.request('my-ext-command', replyChannel, "some-arg");
        
        console.log("Extension returned:", response);
    } catch (err) {
        console.error("Extension request failed:", err);
    }
});
```

{% endcode %}

`NO_TIMEOUT` & `TIMEOUT=`

To change the time to wait before timing out a request, add `TIMEOUT=MS` to the args. This is only used by the Node.js part of Positron and is stripped before sending your args to the Native layer.

{% tabs %}
{% tab title="Custom Timeout" %}
{% code lineNumbers="true" %}

```javascript
 const response = await win.request('cmd', 'reply', "TIMEOUT=1000");
```

{% endcode %}
{% endtab %}

{% tab title="No Timeout" %}
{% hint style="danger" %}
This is not recommended as it can cause memory leaks if the event isn't handled properly
{% endhint %}

{% code lineNumbers="true" %}

```javascript
 const response = await win.request('cmd', 'rply', "NO_TIMEOUT");
```

{% endcode %}
{% endtab %}
{% endtabs %}

#### For fire-and-forget events:

{% code lineNumbers="true" %}

```javascript
mainWindow.on('ready', async () => {
    // Arguments: (commandName, ...args)
    mainWindow.sendCommand("my-ext", "Hello from the JavaScript Backend!");
});
```

{% endcode %}


---

# Agent Instructions: Querying This Documentation

If you need additional information that is not directly available in this page, you can query the documentation dynamically by asking a question.

Perform an HTTP GET request on the current page URL with the `ask` query parameter:

```
GET https://positronjs.gitbook.io/v1/extensions/dispatch-commands.md?ask=<question>
```

The question should be specific, self-contained, and written in natural language.
The response will contain a direct answer to the question and relevant excerpts and sources from the documentation.

Use this mechanism when the answer is not explicitly present in the current page, you need clarification or additional context, or you want to retrieve related documentation sections.
