Spec-Zone.ru › Deno 2

Deno реализует многие стандартные API веб-платформы, доступные в современных браузерах. Это значит, что если вы разрабатывали приложения для веба, то, скорее всего, уже знакомы со многими API Deno. Изучая Deno, вы также углубляете свои знания о веб-платформе.

В этом разделе представлена подробная документация по всем поддерживаемым в Deno API веб-платформы. Вы можете просмотреть все символы, чтобы увидеть полный список или выполнить поиск по категориям. Нажмите на любую функцию или интерфейс, чтобы посмотреть подробную документацию с примерами.

Основные API веб-платформы

Deno поддерживает широкий набор стандартных веб-API:

Сеть и коммуникация

  • fetch — HTTP-запросы в соответствии со спецификацией WHATWG Fetch
  • WebSocket — дуплексная связь через TCP
  • События, отправленные сервером — потоковая передача событий от сервера клиенту
  • BroadcastChannel — обмен сообщениями между контекстами

Хранение и состояние

  • Веб-хранилище — API localStorage и sessionStorage
  • Cache API — интерфейс кэширования HTTP-ответов
  • IndexedDB — хранилище базы данных на стороне клиента

Воркеры и параллелизм

  • Веб-воркеры — выполнение в фоновых потоках
  • SharedArrayBuffer — общая память между воркерами

Потоки и данные

  • Streams API — комбинируемые интерфейсы потоковой передачи данных
  • Сжатие — встроенное сжатие gzip/deflate
  • File API — работа с файлами и объектами Blob

События и DOM

  • Event API — стандартные шаблоны обработки событий
  • CustomEvent — создание и отправка пользовательских событий
  • EventTarget — управление обработчиками событий

Кодирование и криптография

  • TextEncoder/TextDecoder — кодирование и декодирование текста UTF-8
  • Web Crypto — криптографические операции
  • URL API — разбор и обработка URL

Таймеры и производительность

  • Performance API — высокоточное измерение времени
  • Таймеры — setTimeout, setInterval и setImmediate

Структурированное клонирование и передаваемые объекты

Deno поддерживает structuredClone() и postMessage() для клонирования и передачи объектов между контекстами (например, между главным потоком и веб-воркерами).

Сериализуемые типы

Эти типы можно клонировать с помощью structuredClone() и передавать через postMessage():

Тип Примечания
Примитивы string, number, boolean, null, undefined, bigint
Array, Object, Map, Set Включая вложенные структуры и циклические ссылки
Date, RegExp
ArrayBuffer, TypedArray, DataView По умолчанию копируются, либо передаются (см. ниже)
Типы Error Error, EvalError, RangeError, ReferenceError, SyntaxError, TypeError, URIError
Blob Требуется Deno 2.8 или новее
File Требуется Deno 2.8 или новее
DOMException
CryptoKey

Передаваемые типы

Эти типы можно передавать (а не копировать) с помощью параметра transfer в structuredClone() или списка transfer в postMessage(). После передачи исходный объект становится непригодным для использования:

Тип Примечания
ArrayBuffer Перемещает резервную память получателю
MessagePort Передаёт порт в другой контекст
ReadableStream Передаёт поток в другой контекст
WritableStream Передаёт поток в другой контекст
TransformStream Передаёт поток в другой контекст
// Clone a Blob
const blob = new Blob(["hello"], { type: "text/plain" });
const cloned = structuredClone(blob);
console.log(await cloned.text()); // "hello"

// Transfer an ArrayBuffer through a MessageChannel
const buffer = new ArrayBuffer(1024);
const ch = new MessageChannel();
ch.port1.postMessage(buffer, [buffer]);
// buffer.byteLength is now 0 (transferred)

Ключевые преимущества

  • Соответствие стандартам: API соответствуют спецификациям WHATWG и W3C
  • Кроссплатформенность: код работает одинаково в Deno, браузерах и других средах выполнения
  • Без полифилов: нативные реализации обеспечивают оптимальную производительность
  • Готовность к будущему: основано на развивающихся веб-стандартах

Примеры использования

Выполнение HTTP-запросов

const response = await fetch("https://api.github.com/users/denoland");
const data = await response.json();
console.log(data);

Использование веб-воркеров

// main.js
const worker = new Worker(import.meta.resolve("./worker.js"), {
  type: "module",
});

worker.postMessage({ task: "process_data", data: [1, 2, 3] });
worker.onmessage = (e) => console.log("Result:", e.data);
// worker.js
self.onmessage = (e) => {
  const { task, data } = e.data;
  const result = data.map((x) => x * 2);
  self.postMessage(result);
};

Локальное хранилище

// Persist data across sessions
localStorage.setItem("user_preference", "dark_mode");
const preference = localStorage.getItem("user_preference");

Примечания о совместимости

Чтобы проверить, доступен ли API веб-платформы в Deno, обратитесь к документации по интерфейсу на сайте MDN и к таблице совместимости с браузерами.

Большинство API реализовано в соответствии со спецификациями, с некоторыми адаптациями Deno для серверных сред. Примечательные отличия описаны ниже.

fetch

API fetch можно использовать для выполнения HTTP-запросов. Он реализован в соответствии со спецификацией WHATWG fetch.

Отклонения от спецификации

  • В пользовательском агенте Deno нет хранилища файлов cookie. Поэтому заголовок set-cookie ответа не обрабатывается и не удаляется из видимых заголовков ответа.
  • Deno не соблюдает политику одного источника, поскольку пользовательский агент Deno в настоящее время не оперирует понятием источников и не имеет хранилища файлов cookie. Это значит, что Deno не требуется защищать аутентифицированные данные от утечки между источниками. Поэтому Deno не реализует следующие разделы спецификации WHATWG fetch:
    • Раздел 3.1. 'Origin' header.
    • Раздел 3.2. CORS protocol.
    • Раздел 3.5. CORB.
    • Раздел 3.6. 'Cross-Origin-Resource-Policy' header.
    • Atomic HTTP redirect handling.
    • Тип ответа opaqueredirect.
  • Запрос fetch с режимом redirect, равным manual, возвращает ответ basic, а не ответ opaqueredirect.
  • В спецификации расплывчато описано, как следует обрабатывать URL-адреса file:. Firefox — единственный распространённый браузер, в котором реализована загрузка URL-адресов file:, и даже там она по умолчанию не работает. Начиная с Deno 1.16, Deno поддерживает загрузку локальных файлов. Подробности см. в следующем разделе.
  • Защита заголовков request и response реализована, но, в отличие от браузеров, ограничений на допустимые имена заголовков нет.
  • Свойства referrer, referrerPolicy, mode, credentials, cache, integrity, keepalive и window, а также соответствующее им поведение в RequestInit не реализованы. Соответствующие поля отсутствуют в объекте Request.
  • Поддерживается потоковая передача тела запроса (для HTTP/1.1 и HTTP/2). В отличие от текущего предложения по Fetch, реализация поддерживает двунаправленную потоковую передачу.
  • Заголовок set-cookie не объединяется при переборе с помощью итератора headers. Это поведение в процессе стандартизации.

Загрузка локальных файлов

Deno поддерживает загрузку URL-адресов file:. Это упрощает написание кода, использующего один и тот же путь выполнения как на сервере, так и локально, а также позволяет легче создавать код, работающий и с Deno CLI, и с Deno Deploy.

Deno поддерживает только абсолютные URL-адреса файлов, поэтому fetch("./some.json") работать не будет. Однако следует отметить, что если указан --location, то относительные URL-адреса используют --location в качестве базового адреса, но URL-адрес file: нельзя передать в качестве --location.

Чтобы загрузить ресурс относительно текущего модуля — независимо от того, локальный модуль или удалённый, — используйте import.meta.url в качестве базового адреса. Например:

const response = await fetch(new URL("./config.json", import.meta.url));
const config = await response.json();

Примечания о загрузке локальных файлов:

  • Для чтения ресурсов применяются разрешения, поэтому для чтения локального файла требуется соответствующее разрешение --allow-read.
  • Локальная загрузка поддерживает только метод GET; при использовании любого другого метода промис будет отклонён.
  • Если файл не существует, промис просто отклоняется с неопределённой ошибкой TypeError. Это сделано для предотвращения потенциальных атак по сбору данных об окружении.
  • В ответе не устанавливаются заголовки. Поэтому потребитель должен самостоятельно определять такие параметры, как тип или длина содержимого.
  • Тела ответов передаются потоками со стороны Rust, поэтому большие файлы доступны частями, а передачу можно отменить.

CustomEvent и EventTarget

DOM Event API можно использовать для отправки событий приложения и прослушивания этих событий. Он реализован в соответствии со спецификацией WHATWG DOM.

Отклонения Event API

  • События не всплывают, поскольку в Deno нет иерархии DOM, а значит, нет дерева, по которому события могли бы всплывать или перехватываться.
  • Свойству timeStamp всегда присваивается значение 0.

Определения типов

Определения TypeScript для реализованных веб-API находятся в файлах lib.deno.shared_globals.d.ts и lib.deno.window.d.ts.

Определения, относящиеся к воркерам, находятся в файле lib.deno.worker.d.ts.

Location

Deno поддерживает глобальный объект location из веб-платформы.

Флаг location

В процессе Deno нет «веб-страницы», URL-адрес которой можно было бы использовать в качестве location. Вместо этого пользователи могут имитировать адрес документа, указав его в CLI с помощью флага --location. Это может быть URL-адрес http или https.

// deno run --location https://example.com/path main.ts

console.log(location.href);
// "https://example.com/path"

Для этого необходимо передать --location <href>. Если этого не сделать, любая попытка обратиться к глобальному объекту location приведёт к ошибке.

// deno run main.ts

console.log(location.href);
// error: Uncaught ReferenceError: Access to "location", run again with --location <href>.

Изменение location или любого из его полей обычно вызывает навигацию в браузерах. В Deno это неприменимо, поэтому в такой ситуации будет выброшена ошибка.

// deno run --location https://example.com/path main.ts

location.pathname = "./foo";
// error: Uncaught NotSupportedError: Cannot set "location.pathname".

Расширенное использование

В вебе при разрешении ресурсов (за исключением модулей) в качестве основы для относительных URL-адресов обычно используется значение location.href. Это влияет на некоторые веб-API, используемые в Deno.

Fetch API

// deno run --location https://api.github.com/ --allow-net main.ts

const response = await fetch("./orgs/denoland");
// Fetches "https://api.github.com/orgs/denoland".

Вызов fetch() выше вызвал бы ошибку, если бы не был передан флаг --location, поскольку в Deno нет аналога веб-адреса, который можно было бы использовать в качестве основы.

Модули воркеров

// deno run --location https://example.com/index.html --allow-net main.ts

const worker = new Worker("./workers/hello.ts", { type: "module" });
// Fetches worker module at "https://example.com/workers/hello.ts".
Примечание

В приведённых выше случаях предпочтительно передавать URL-адреса полностью, а не полагаться на --location. При необходимости можно вручную задать базовый адрес относительного URL с помощью конструктора URL.

Флаг --location предназначен для тех, кому нужно имитировать адрес документа для конкретной цели и кто понимает, что это будет работать только на уровне приложения. Однако его также можно использовать, чтобы подавить ошибки, вызванные нецелесообразным обращением зависимости к глобальному объекту location.

Веб-хранилище

Web Storage API предоставляет API для хранения строковых ключей и значений. Сохранение данных работает аналогично браузеру; ограничение хранилища составляет 10 МБ. Глобальный объект sessionStorage сохраняет данные только для текущего контекста выполнения, тогда как localStorage сохраняет их между запусками.

В браузере localStorage сохраняет данные отдельно для каждого источника (фактически, для комбинации протокола, имени хоста и порта). Начиная с Deno 1.16, Deno использует набор правил для определения уникального расположения хранилища:

  • При использовании флага --location для уникального хранения данных используется источник location. Это значит, что location http://example.com/a.ts, http://example.com/b.ts и http://example.com:80/ будут использовать одно и то же хранилище, а https://example.com/ — другое.
  • Если location не указан, но задан конфигурационный файл --config, используется абсолютный путь к этому файлу. Это значит, что deno run --config deno.jsonc a.ts и deno run --config deno.jsonc b.ts будут использовать одно и то же хранилище, а deno run --config tsconfig.json a.ts — другое.
  • Если не заданы ни конфигурация, ни location, Deno использует абсолютный путь к главному модулю, чтобы определить, какие данные хранилища являются общими. Deno REPL генерирует «синтетический» главный модуль на основе текущего рабочего каталога, из которого запущен deno. Это значит, что несколько запусков REPL из одного каталога будут использовать одни и те же сохранённые данные localStorage.

Для установки, получения и удаления элементов из localStorage можно использовать следующий код:

// Set an item in localStorage
localStorage.setItem("myDemo", "Deno App");

// Read an item from localStorage
const cat = localStorage.getItem("myDemo");

// Remove an item from localStorage
localStorage.removeItem("myDemo");

// Remove all items from localStorage
localStorage.clear();

Веб-воркеры

Deno поддерживает Web Worker API.

Воркеры можно использовать для выполнения кода в нескольких потоках. Каждый экземпляр Worker выполняется в отдельном потоке, выделенном только для этого воркера.

В настоящее время Deno поддерживает только воркеры типа module, поэтому при создании нового воркера необходимо передавать параметр type: "module".

Использование относительных спецификаторов модулей в главном воркере поддерживается только при передаче --location <href> в CLI. Для переносимости это не рекомендуется. Вместо этого можно использовать конструктор URL и import.meta.url, чтобы легко создать спецификатор для расположенного рядом скрипта. Однако у выделенных воркеров location есть по умолчанию, поэтому им эта возможность доступна без дополнительных настроек.

// Good
new Worker(import.meta.resolve("./worker.js"), { type: "module" });

// Bad
new Worker(import.meta.resolve("./worker.js"));
new Worker(import.meta.resolve("./worker.js"), { type: "classic" });
new Worker("./worker.js", { type: "module" });

Как и в обычных модулях, в модулях воркеров можно использовать верхнеуровневый await. Однако обязательно зарегистрируйте обработчик сообщений до первого await, иначе сообщения могут быть потеряны. Это не ошибка Deno, а лишь неудачное взаимодействие функций; такое же поведение наблюдается во всех браузерах, поддерживающих воркеры-модули.

import { delay } from "jsr:@std/async@1/delay";

// First await: waits for a second, then continues running the module.
await delay(1000);

// The message handler is only set after that 1s delay, so some of the messages
// that reached the worker during that second might have been fired when no
// handler was registered.
self.onmessage = (evt) => {
  console.log(evt.data);
};

Разрешения при создании экземпляра

Создание нового экземпляра Worker аналогично динамическому импорту, поэтому для этого действия Deno требует соответствующее разрешение.

Для воркеров, использующих локальные модули, требуется разрешение --allow-read:

main.ts
new Worker(import.meta.resolve("./worker.ts"), { type: "module" });
worker.ts
console.log("hello world");
self.close();
$ deno run main.ts
error: Uncaught PermissionDenied: read access to "./worker.ts", run again with the --allow-read flag

$ deno run --allow-read main.ts
hello world

Для воркеров, использующих удалённые модули, требуется разрешение --allow-net:

main.ts
new Worker("https://example.com/worker.ts", { type: "module" });
worker.ts
// This file is hosted at https://example.com/worker.ts
console.log("hello world");
self.close();
$ deno run main.ts
error: Uncaught PermissionDenied: net access to "https://example.com/worker.ts", run again with the --allow-net flag

$ deno run --allow-net main.ts
hello world

Использование Deno в воркере

main.js
const worker = new Worker(import.meta.resolve("./worker.js"), {
  type: "module",
});

worker.postMessage({ filename: "./log.txt" });
worker.js
self.onmessage = async (e) => {
  const { filename } = e.data;
  const text = await Deno.readTextFile(filename);
  console.log(text);
  self.close();
};
log.txt
hello world
$ deno run --allow-read main.js
hello world

Настройка разрешений воркера

Внимание

Это нестабильная функция Deno. Подробнее см. в разделе нестабильные функции.

Разрешения, доступные воркеру, аналогичны флагам разрешений CLI: любое разрешение, включённое в CLI, можно отключить на уровне Worker API. Подробное описание каждого параметра разрешений см. в документации по безопасности.

По умолчанию воркер наследует разрешения потока, в котором он был создан. Однако, чтобы пользователи могли ограничить доступ этого воркера, в Worker API предусмотрен параметр deno.permissions.

Для разрешений с гранулярным доступом можно передать список ресурсов, к которым воркеру будет разрешён доступ. Для разрешений, которые можно только включить или отключить, можно передать соответственно true или false:

const worker = new Worker(import.meta.resolve("./worker.js"), {
  type: "module",
  deno: {
    permissions: {
      net: [
        "deno.land",
      ],
      read: [
        new URL("./file_1.txt", import.meta.url),
        new URL("./file_2.txt", import.meta.url),
      ],
      write: false,
    },
  },
});

В разрешения с гранулярным доступом можно передавать как абсолютные, так и относительные пути. Однако учитывайте, что относительные пути будут разрешаться относительно файла, в котором создаётся воркер, а не относительно расположения файла воркера:

const worker = new Worker(
  new URL("./worker/worker.js", import.meta.url).href,
  {
    type: "module",
    deno: {
      permissions: {
        read: [
          "/home/user/Documents/deno/worker/file_1.txt",
          "./worker/file_2.txt",
        ],
      },
    },
  },
);

И deno.permissions, и его дочерние элементы поддерживают параметр "inherit", который означает, что воркер будет использовать разрешения родительского элемента:

// This worker will inherit its parent permissions
const worker = new Worker(import.meta.resolve("./worker.js"), {
  type: "module",
  deno: {
    permissions: "inherit",
  },
});
// This worker will inherit only the net permissions of its parent
const worker = new Worker(import.meta.resolve("./worker.js"), {
  type: "module",
  deno: {
    permissions: {
      env: false,
      hrtime: false,
      net: "inherit",
      ffi: false,
      read: false,
      run: false,
      write: false,
    },
  },
});

Если не указать параметр deno.permissions или один из его дочерних элементов, воркер по умолчанию унаследует разрешения:

// This worker will inherit its parent permissions
const worker = new Worker(import.meta.resolve("./worker.js"), {
  type: "module",
});
// This worker will inherit all the permissions of its parent BUT net
const worker = new Worker(import.meta.resolve("./worker.js"), {
  type: "module",
  deno: {
    permissions: {
      net: false,
    },
  },
});

Чтобы полностью отключить разрешения воркера, передайте "none" параметру deno.permissions:

// This worker will not have any permissions enabled
const worker = new Worker(import.meta.resolve("./worker.js"), {
  type: "module",
  deno: {
    permissions: "none",
  },
});

Отклонения других API от спецификаций

Cache API

Реализованы только следующие API:

  • CacheStorage::open()
  • CacheStorage::has()
  • CacheStorage::delete()
  • Cache::match()
  • Cache::put()
  • Cache::delete()

Несколько отличий от браузеров:

  1. В API нельзя передавать относительные пути. Запрос может быть экземпляром Request или URL либо строкой URL.
  2. match() и delete() пока не поддерживают параметры запроса.

© 2018–2025 the Deno authors
Licensed under the MIT License.
https://docs.deno.com/api/web/about

Spec-Zone.ru

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