restate / v1.0.0
Fiabil prin design
Ce garantează restate când stocarea e lentă, eșuează sau lipsește și cum se citesc erorile pe care le raportează.
Pe această pagină
GaranțiiSalvări în ordineÎncercațiCând încărcarea eșueazăSalvează și închideStocarea nu e disponibilăValidarea și migrarea datelor salvateStocare proprieLimite și timpi de expirareCoduri de eroareGaranții
Acest comportament face parte din contractul 1.0 și este acoperit de testele pachetului.
| Situație | Ce face restate |
|---|---|
Mai multe salvări una după alta | Le rulează în ordine pentru fiecare store; o salvare din coadă scrie cea mai nouă valoare. |
O înregistrare nu s-a încărcat | autoSave și salvările în bloc o omit cu LOAD_FAILED; doar un save() explicit o înlocuiește. |
Componenta se demontează în timpul salvării | Salvarea cerută se încheie; scrierile ulterioare în store-ul distrus sunt ignorate. |
Stocarea nu e disponibilă | Store-ul rulează în memorie, status().available este false, iar salvările sunt respinse. |
Un adaptor se blochează | Operațiunea expiră după operationTimeoutMs, iar lucrul următor așteaptă ca adaptorul să termine. |
Prea mult lucru în așteptare | Operațiunile noi sunt respinse cu QUEUE_FULL în loc să crească fără limită. |
Salvări în ordine
Operațiunile unui store nu se suprapun niciodată. O salvare care pornește cât alta așteaptă preia cea mai nouă valoare, așa că salvarea la fiecare schimbare scrie ultima stare fără a umple coada.
useDraft.set('A');
const first = useDraft.save(); // writes "A"
useDraft.set('B');
const second = useDraft.save(); // waits in the queue
useDraft.set('C');
const third = useDraft.save(); // joins the waiting save
await Promise.all([first, second, third]); // ['A', 'C', 'C'] — two writesÎncercați
Încetiniți stocarea, faceți scrierile să eșueze sau eliminați stocarea cu totul.
Se pregătește exemplul…
Când încărcarea eșuează
restateManager.ready este respins cu BULK_OPERATION_FAILED și listează fiecare store care a eșuat. Până se încarcă acea înregistrare, autoSave și saveAll nu o înlocuiesc și raportează LOAD_FAILED.
Reîncercați cu initialize() pentru a păstra modificările și a le salva, apelați restore() pentru a renunța la ele sau save() pentru a suprascrie intenționat înregistrarea.
try {
await restateManager.ready;
} catch (error) {
// BULK_OPERATION_FAILED: one entry per store that could not load.
for (const { store, error: cause } of error.failures) {
console.error(store.key, cause.code);
}
}Salvează și închide
O salvare cerută înainte de demontare se încheie oricum, așa că handlerul „Salvează și închide” nu trebuie să aștepte.
function Document({ onClose }) {
const useDraft = useRestateScope((scope) => persistedRestate('', { scope, key: 'draft' }));
const saveAndClose = () => {
useDraft.save(); // finishes even after this component unmounts
onClose();
};
// …
}Validarea și migrarea datelor salvate
version, migrate și validate vă protejează de înregistrări vechi sau corupte. validate rulează înainte de salvare și după restaurare sau migrare.
import { persistedRestate } from '@kkwaenggwari/restate';
const useSettings = persistedRestate(
{ theme: 'system' },
{
key: 'settings',
version: 2,
migrate(value, from, to) {
if (from === 1 && to === 2 && typeof value?.darkMode === 'boolean') {
return { theme: value.darkMode ? 'dark' : 'light' };
}
throw new Error('Unsupported stored version');
},
validate: (value) => ['system', 'light', 'dark'].includes(value?.theme),
},
);Stocare proprie
Merge orice obiect cu getItem, setItem și removeItem. Metodele pot returna valori sau Promise-uri; isAvailable este opțional.
import { persistedRestate } from '@kkwaenggwari/restate';
const sessionStorageAdapter = {
isAvailable: () => typeof sessionStorage !== 'undefined',
getItem: (key) => sessionStorage.getItem(key),
setItem: (key, value) => sessionStorage.setItem(key, value),
removeItem: (key) => sessionStorage.removeItem(key),
};
export const useFilters = persistedRestate(
{ query: '' },
{
key: 'filters',
storage: sessionStorageAdapter,
},
);Limite și timpi de expirare
Stabiliți cât poate dura o operațiune, câte pot aștepta și cât de mare poate fi o valoare.
persistedRestate(value, {
key: 'draft',
operationTimeoutMs: 10_000, // default 30000
maxPendingOperations: 64, // default 256
maxStorageCharacters: 1_000_000,
});Coduri de eroare
Erorile create de restate au name RestateError, un code și, pentru store-urile salvate, un key. Adaptoarele de stocare și callback-urile pot respinge cu propriile erori.
| Cod | Semnificație |
|---|---|
BULK_OPERATION_FAILED | Un apel în bloc precum restateManager.ready sau saveAll a avut eșecuri; vedeți error.failures. |
INDEXEDDB_ABORTED | O tranzacție IndexedDB a fost abandonată. |
INDEXEDDB_BLOCKED | Deschiderea bazei de date a fost blocată de o conexiune din altă filă. |
INDEXEDDB_CONNECTION_CLOSING | Conexiunea la baza de date se închidea când a pornit cererea. |
INDEXEDDB_OPEN_FAILED | Baza de date nu a putut fi deschisă. |
INDEXEDDB_REQUEST_FAILED | O cerere IndexedDB a eșuat. |
INDEXEDDB_STORE_MISSING | Baza de date existentă nu are object store-ul. |
INVALID_STORAGE_RECORD | Înregistrarea salvată nu este o înregistrare restate validă. |
INVALID_STORED_VALUE | Valoarea nu a trecut de validate. |
LIFECYCLE_LIMIT | Un updater a pornit și s-a oprit în mod repetat. |
LOAD_FAILED | Înregistrarea nu s-a putut încărca, deci salvarea automată sau în bloc nu a înlocuit-o. |
MMKV_UNAVAILABLE | react-native-mmkv nu s-a putut încărca. |
MULTIPLE_ERRORS | Mai multe callback-uri au eșuat într-o singură operațiune; vedeți error.errors. |
NOTIFICATION_LIMIT | Observatorii au tot programat modificări într-o buclă. |
OBSERVER_ERROR | Un listener sau un callback de ciclu de viață a aruncat o eroare. |
OPERATION_ABORTED | O operațiune de stocare a fost anulată. |
QUEUE_FULL | Așteptau mai multe operațiuni decât permite maxPendingOperations. |
REENTRANT_SETTER | Un updater de stare a încercat să modifice același store în timp ce rula. |
SCOPE_DESTROYED | Un scope distrus a fost folosit pentru a crea store-uri. |
SEQUENCE_EXHAUSTED | O secvență internă a rămas fără identificatori. |
STORAGE_BLOCKED | Un apel anterior al adaptorului nu s-a încheiat după expirare sau anulare. |
STORAGE_TIMEOUT | O operațiune a durat mai mult decât operationTimeoutMs. |
STORAGE_UNAVAILABLE | Stocarea nu poate fi folosită aici; store-ul continuă să ruleze în memorie. |
STORAGE_VALUE_TOO_LARGE | Valoarea codificată depășește maxStorageCharacters. |
STORAGE_VERSION_MISMATCH | Înregistrarea are altă versiune și nicio funcție migrate nu o tratează. |
STORE_DESTROYED | Cineva s-a abonat la un store distrus sau i-a cerut să folosească stocarea. |