Platforma internetowa oferuje deweloperom coraz więcej narzędzi do tworzenia dopracowanych, wydajnych aplikacji internetowych. Najważniejsze jest to, że WebAssembly (Wasm) otworzył drogę do szybkich i wydajnych aplikacji internetowych, a technologie takie jak Emscripten pozwalają deweloperom ponownie używać sprawdzonego kodu w internecie. Aby w pełni wykorzystać ten potencjał, deweloperzy muszą mieć taką samą moc i elastyczność w zakresie pamięci.
Właśnie w takich sytuacjach przydaje się interfejs Storage Foundation API. Storage Foundation API to nowy, szybki i niedostrzegalny interfejs API do przechowywania danych, który umożliwia korzystanie z nowych i bardzo oczekiwanych przypadków użycia w internecie, takich jak wdrażanie wydajnych baz danych i płynne zarządzanie dużymi plikami tymczasowymi. Dzięki temu nowemu interfejsowi deweloperzy mogą „wnosić własny magazyn” do sieci, zmniejszając różnice w funkcjach między kodem internetowym a kodem platformy.
Interfejs Storage Foundation API jest zaprojektowany tak, aby przypominać bardzo podstawowy system plików, co daje deweloperom elastyczność dzięki udostępnianiu ogólnych, prostych i wydajnych prymitywów, na których mogą budować komponenty wyższego poziomu. Aplikacje mogą korzystać z najlepszego narzędzia do swoich potrzeb, zapewniając odpowiednią równowagę między łatwością obsługi, wydajnością i niezawodnością.
Dlaczego internet potrzebuje innego interfejsu API do przechowywania danych?
Platforma internetowa oferuje deweloperom wiele opcji miejsca na dane, z których każda jest zaprojektowana pod kątem konkretnych przypadków użycia.
- Niektóre z tych opcji wyraźnie nie pokrywają się z tą propozycją, ponieważ umożliwiają przechowywanie tylko bardzo małych ilości danych, np. pliki cookie lub interfejs Web Storage API, który składa się z mechanizmów
sessionStorage
ilocalStorage
. - Inne opcje zostały już wycofane z różnych powodów, np. interfejs API „File and Directory Entries” czy WebSQL.
- Interfejs File System Access API ma podobną powierzchnię interfejsu API, ale służy do interakcji z systemem plików klienta i dostępu do danych, które mogą nie należeć do pochodzenia ani nawet do przeglądarki. Takie rozróżnienie wiąże się z bardziej rygorystycznymi zasadami dotyczącymi bezpieczeństwa i wyższymi kosztami wydajności.
- Interfejs IndexedDB API może służyć jako backend w niektórych przypadkach użycia interfejsu Storage Foundation API. Na przykład Emscripten zawiera IDBFS, trwały system plików oparty na IndexedDB. Jednak ponieważ IndexedDB jest zasadniczo magazynem klucz-wartość, wiąże się z nim znaczne ograniczenie wydajności. Co więcej, bezpośredni dostęp do podseekcji pliku jest jeszcze trudniejszy i wolniejszy w IndexedDB.
- Na koniec warto wspomnieć, że interfejs CacheStorage jest szeroko obsługiwany i dostosowany do przechowywania dużych danych, takich jak zasoby aplikacji internetowej, ale wartości są niezmienne.
Interfejs Storage Foundation API to próba wyeliminowania wszystkich luk w poprzednich opcjach przechowywania danych poprzez umożliwienie wydajnego przechowywania dużych plików o zmiennej treści zdefiniowanych w źródle aplikacji.
Sugerowane przypadki użycia interfejsu Storage Foundation API
Przykłady witryn, które mogą korzystać z tego interfejsu API:
- aplikacje do produktywności lub kreatywności, które działają na dużych ilościach danych wideo, audio lub obrazów; Takie aplikacje mogą przenosić segmenty na dysk zamiast przechowywać je w pamięci.
- Aplikacje, które korzystają z trwałego systemu plików dostępnego z poziomu Wasm i które wymagają większej wydajności niż ta, jaką gwarantuje IDBFS.
Czym jest interfejs Storage Foundation API?
Interfejs API składa się z 2 głównych części:
- wywołania systemu plików, które zapewniają podstawowe funkcje interakcji z plikami i ścieżkami do plików;
- uchwyty plików, które zapewniają dostęp do odczytu i zapisu do istniejącego pliku;
Wywołania systemu plików
Interfejs Storage Foundation API wprowadza nowy obiekt storageFoundation
, który znajduje się w obiekcie window
i zawiera kilka funkcji:
storageFoundation.open(name)
: powoduje otwarcie pliku o podanej nazwie, jeśli istnieje, w przeciwnym razie tworzy nowy plik. Zwraca obietnicę, która jest wypełniana po otwarciu pliku.
storageFoundation.delete(name)
: usuwa plik o podanej nazwie. Zwraca obietnicę, która zostanie spełniona po usunięciu pliku.storageFoundation.rename(oldName, newName)
: zmienia nazwę pliku z poprzedniej na nową. Zwraca obietnicę, która zostanie spełniona po zmianie nazwy pliku.storageFoundation.getAll()
: zwraca obietnicę, która zwraca tablicę wszystkich nazw plików.storageFoundation.requestCapacity(requestedCapacity)
: żąda nowej pojemności (w bajtach) do wykorzystania przez bieżący kontekst wykonania. Zwraca obietnicę, która zwraca pozostałą ilość dostępnej pojemności.
storageFoundation.releaseCapacity(toBeReleasedCapacity)
: zwalnia określoną liczbę bajtów z bieżącego kontekstu wykonania i zwraca obietnicę, która zwraca pozostałą pojemność.storageFoundation.getRemainingCapacity()
: zwraca obietnicę, która zwraca pojemność dostępną w bieżącym kontekście wykonania.
uchwyty plików;
Praca z plikami odbywa się za pomocą następujących funkcji:
NativeIOFile.close()
: zamyka plik i zwraca obietnicę zakończoną po zakończeniu operacji.NativeIOFile.flush()
: synchronizuje (czyli czyści) stan pliku w pamięci z urządzeniem pamięci masowej i zwraca obietnicę, która zostanie spełniona po zakończeniu operacji.
NativeIOFile.getLength()
: zwraca obietnicę, która zwraca długość pliku w bajtach.NativeIOFile.setLength(length)
: ustawia długość pliku w bajtach i zwraca obietnicę, która zostanie spełniona po zakończeniu operacji. Jeśli nowa długość jest mniejsza niż bieżąca długość, bajty są usuwane od końca pliku. W przeciwnym razie plik jest rozszerzany o bajty o wartości 0.NativeIOFile.read(buffer, offset)
: odczytuje zawartość pliku w danym przesunięciu za pomocą bufora, który jest wynikiem przeniesienia danego bufora, który jest następnie odłączony. ZwracaNativeIOReadResult
z przekazanym buforem i liczbą bajtów, które zostały odczytane.NativeIOReadResult
to obiekt, który składa się z 2 elementów:buffer
:ArrayBufferView
, co jest wynikiem przeniesienia bufora przekazanego doread()
. Ma on ten sam typ i długość co bufor źródłowy.readBytes
: liczba bajtów odczytanych do plikubuffer
. Jeśli wystąpi błąd lub zakres odczytu wykracza poza koniec pliku, może on być mniejszy niż rozmiar bufora. Jeśli zakres odczytu wykracza poza koniec pliku, pole ma wartość 0.
NativeIOFile.write(buffer, offset)
: zapisuje zawartość danego bufora w pliku z podanym przesunięciem. Bufor jest przesyłany przed zapisaniem danych, więc zostaje odłączony. ZwracaNativeIOWriteResult
z przekazanym buforem i liczbą bajtów, które zostały pomyślnie zapisane. Plik zostanie wydłużony, jeśli zakres zapisu przekroczy jego długość.NativeIOWriteResult
to obiekt składający się z 2 wpisów:buffer
:ArrayBufferView
, który jest wynikiem przeniesienia bufora przekazanego dowrite()
. Ma on ten sam typ i długość co bufor źródłowy.writtenBytes
: liczba bajtów zapisanych w plikubuffer
. Jeśli wystąpi błąd, może to być mniejsze niż rozmiar bufora.
Pełne przykłady
Aby lepiej wyjaśnić omówione powyżej zagadnienia, podajemy 2 pełne przykłady, które pokazują różne etapy cyklu życia plików Storage Foundation.
Otwieranie, pisanie, czytanie, zamykanie
// Open a file (creating it if needed).
const file = await storageFoundation.open('test_file');
try {
// Request 100 bytes of capacity for this context.
await storageFoundation.requestCapacity(100);
const writeBuffer = new Uint8Array([64, 65, 66]);
// Write the buffer at offset 0. After this operation, `result.buffer`
// contains the transferred buffer and `result.writtenBytes` is 3,
// the number of bytes written. `writeBuffer` is left detached.
let result = await file.write(writeBuffer, 0);
const readBuffer = new Uint8Array(3);
// Read at offset 1. `result.buffer` contains the transferred buffer,
// `result.readBytes` is 2, the number of bytes read. `readBuffer` is left
// detached.
result = await file.read(readBuffer, 1);
// `Uint8Array(3) [65, 66, 0]`
console.log(result.buffer);
} finally {
file.close();
}
Otwieranie, wyświetlanie, usuwanie
// Open three different files (creating them if needed).
await storageFoundation.open('sunrise');
await storageFoundation.open('noon');
await storageFoundation.open('sunset');
// List all existing files.
// `["sunset", "sunrise", "noon"]`
await storageFoundation.getAll();
// Delete one of the three files.
await storageFoundation.delete('noon');
// List all remaining existing files.
// `["sunrise", "noon"]`
await storageFoundation.getAll();
Prezentacja
Możesz zapoznać się z demo interfejsu Storage Foundation API, korzystając z załączonego poniżej kodu. Możesz tworzyć pliki, zmieniać ich nazwy, zapisywać w nich i odczytywać je, a także wyświetlać dostępną pojemność, o którą prosisz w przypadku wprowadzania zmian. Kod źródłowy wersji demonstracyjnej znajdziesz na stronie Glitch.
Zabezpieczenia i uprawnienia
Zespół Chromium zaprojektował i wdrżał interfejs Storage Foundation API, korzystając z podstawowych zasad określonych w artykule Kontrolowanie dostępu do zaawansowanych funkcji platformy internetowej, w tym kontroli użytkownika, przejrzystości i ergonomiki.
Dostęp do interfejsu Storage Foundation API jest zgodny z wzorcem podanym w innych nowoczesnych interfejsach API do przechowywania danych w internecie, co oznacza, że źródło może uzyskiwać dostęp tylko do danych utworzonych samodzielnie. Jest też ograniczona do kontekstów niezabezpieczonych.
Kontrola użytkownika
Limit miejsca na dane będzie używany do dystrybucji dostępu do miejsca na dysku i zapobiegania nadużyciom. Pamięć, którą chcesz wykorzystać, musi być najpierw zarezerwowana. Podobnie jak w przypadku innych interfejsów API miejsca na dane użytkownicy mogą zwolnić miejsce zajęte przez interfejs Storage Foundation API w przeglądarce.
Przydatne linki
- Publiczne wyjaśnienie
- Demonstracja interfejsu Storage Foundation API | źródło demonstracji interfejsu Storage Foundation API
- Błąd śledzenia w Chromium
- Wpis na temat ChromeStatus.com
- Składnik Blink:
Blink>Storage>NativeIO
- Sprawdzanie tagów
- Intencja tworzenia prototypu
- Wątek z WebKit
- Wątek na Mozilla
Podziękowania
Interfejs Storage Foundation API został określony i wdrożony przez Emanuela Krivoya i Richarda Stotza. Ten artykuł został sprawdzony przez Pete LePage i Joe Medley.
Baner powitalny z filmu Markus Spiske w Unsplash.