Spec-Zone.ru › Deno 2

Привязки

Доступно в Deno 2.9

deno desktop доступно начиная с Deno v2.9.0. Если у вас более ранняя версия, обновите Deno, чтобы использовать эту возможность.

win.bind(name, handler) предоставляет функцию на стороне Deno веб-представлению. Из веб-представления вызовите её как bindings.<name>(args), и вызов вернёт Promise, которое разрешится значением, возвращённым обработчиком.

Сторона Deno
win.bind("readSettings", async () => {
  const text = await Deno.readTextFile("settings.json");
  return JSON.parse(text);
});

win.bind("saveSettings", async (settings) => {
  await Deno.writeTextFile("settings.json", JSON.stringify(settings, null, 2));
});
Сторона веб-представления
const settings = await bindings.readSettings();
settings.theme = "dark";
await bindings.saveSettings(settings);

Как это работает

Привязки — это не IPC. Среда выполнения Deno и сервер отрисовки работают как потоки / процессы в одном адресном пространстве (CEF) или в согласованной группе процессов (WebView). Вызовы передаются по внутрипроцессным каналам, а сервер отправляет их на выполнение из своего цикла обработки событий.

Это позволяет избежать межпроцессного обмена данными туда и обратно, который требуют основанные на сокетах фреймворки IPC (ipcMain / ipcRenderer Electron, invoke Tauri). Аргументы и результаты по-прежнему кодируются при пересечении границы между областями видимости, но передача данных происходит внутри процесса: без сокетов и планирования между процессами.

На практике привязки работают достаточно быстро, поэтому для типичных задач приложения вам не нужно беспокоиться о частоте вызовов.

Прокси веб-представления

bindings на стороне веб-представления — это Proxy. При каждом обращении к свойству функция создаётся по запросу:

bindings.foo; // function
bindings.foo("a", 1); // Promise<unknown>

Прокси не проверяет имена: если вместо bindings.readSettings указать bindings.readSetings, ошибки при обращении к свойству не возникнет; она появится при вызове (вызов будет отклонён, поскольку такая привязка не зарегистрирована).

Семантика аргументов и возвращаемых значений

Аргументы и возвращаемые значения кодируются в JSON при передаче между веб-представлением и средой выполнения Deno. Это означает следующее:

  • Обычные объекты, массивы, строки, числа, логические значения и null передаются без изменений.
  • Uint8Array поддерживается для передачи двоичных данных.
  • undefined и необязательные свойства удаляются при сериализации.
  • Date, Map, Set, RegExp, типизированные массивы, кроме Uint8Array, и ArrayBuffer: не сохраняются. Прежде чем отправлять их, преобразуйте их в структуру, совместимую с JSON (Date становится строкой, а Map становится {}).
  • Функции, узлы DOM, прототипы и циклические ссылки нельзя передавать.
  • Ошибки, выброшенные обработчиком, передаются веб-представлению как { name, message, stack } (см. раздел Ошибки ниже), а не как экземпляр Error.

Используйте простые данные и Uint8Array с обеих сторон.

Асинхронные обработчики

Обработчики могут быть синхронными или асинхронными. Веб-представление всегда получает Promise:

win.bind("now", () => Date.now()); // sync
win.bind("delay", async (ms) => { // async
  await new Promise((r) => setTimeout(r, ms));
});
const t = await bindings.now();
await bindings.delay(500);

Ошибки

Если обработчик выбрасывает исключение — синхронно или через отклонённый промис, — вызов со стороны веб-представления будет отклонён:

win.bind("readFile", async (path) => {
  return await Deno.readTextFile(path);
});
try {
  await bindings.readFile("/missing");
} catch (e) {
  console.error(e); // NotFound: …
}

Веб-представление получает ошибку как обычный объект { name, message, stack }. Чтобы определить тип ошибки, проверьте error.name.

Удаление привязки

win.unbind("readSettings");

Удаляет привязку. Последующие вызовы bindings.readSettings() будут отклонены.

Разрешения

Привязки выполняются в среде выполнения Deno, поэтому наследуют разрешения процесса. Для привязки, вызывающей Deno.readTextFile, требуется, чтобы при запуске было предоставлено разрешение --allow-read. Веб-представление не может расширить разрешения среды выполнения с помощью привязок.

Обычно настольные приложения запускаются с широкими разрешениями, встроенными в скомпилированный бинарный файл (deno desktop в настоящее время не запрашивает отдельного разрешения во время выполнения). Если вы предоставляете привязки, работающие с файловой системой или сетью, проверяйте входные данные так же тщательно, как и в любом коде, пересекающем границу доверия.

Привязки для каждого окна

Привязки задаются отдельно для каждого окна. Привязка, зарегистрированная в winA, недоступна из веб-представления winB. Чтобы использовать привязку в нескольких окнах, зарегистрируйте её в каждом из них:

function bindShared(win: Deno.BrowserWindow) {
  win.bind("now", () => Date.now());
  win.bind("readSettings", readSettings);
}

const main = new Deno.BrowserWindow(); // adopts the startup window
bindShared(main);

const settings = new Deno.BrowserWindow();
bindShared(settings);

Типобезопасность

Встроенного моста типов между win.bind() на стороне Deno и bindings.<name>() на стороне веб-представления нет. Эти стороны работают в отдельных областях видимости JS.

Небольшой общий файл деклараций типов позволит описать обе стороны:

bindings.d.ts
export interface Bindings {
  readSettings(): Promise<Settings>;
  saveSettings(s: Settings): Promise<void>;
  now(): Promise<number>;
}

declare global {
  // Make `bindings` typed in the webview.
  const bindings: Bindings;
}

export interface Settings {
  theme: "light" | "dark";
}

Подключите его в tsconfig веб-представления или конфигурации проекта Deno и используйте один и тот же интерфейс Bindings для проверки типов вызовов win.bind. Несоответствия между регистрацией и декларацией будут обнаружены при компиляции на стороне Deno.

Переход с Electron

Если вы переходите с ipcMain.handle('channel', handler) / ipcRenderer.invoke('channel', ...) в Electron, принцип работы остаётся тем же:

Electron deno desktop
ipcMain.handle('channel', (e, ...args) => result) win.bind('channel', (...args) => result)
ipcRenderer.invoke('channel', ...args) bindings.channel(...args)
contextBridge.exposeInMainWorld('api', {...}) Не требуется: bindings доступен по умолчанию.

У объекта event, который Electron передаёт первым аргументом, нет аналога, поскольку отдельного процесса, которому можно было бы приписать вызов, не существует. Контекст каждого окна связан с объектом win, в котором вы зарегистрировали привязку.

Последнее обновление: 25 июня 2026 г.

© 2018–2025 the Deno authors
Licensed under the MIT License.
https://docs.deno.com/runtime/desktop/bindings

Spec-Zone.ru

Настройки Оффлайн Что нового Помощь О нас
Spec-Zone .ru
спецификации, руководства, описания, API