Ideje bezárkózni
A Javascript aszinkron funkciói nem igazán párhuzamosak. Az ES2017-től kezdődően a Javascript támogatja az egyidejű függvényhívásokat. A különbséget Madhavan Nagarajan nagyon szépen összefoglalja a következő állításban (link megtalálható a függelékben).
Az egyidejűség arról szól, hogy egyszerre rengeteg dologgal foglalkozzunk. A párhuzamosság annyi, hogy egyszerre sok mindent csinálunk.
A Javascript párhuzamosságának megvalósulása csökkenti a funkcionalitását, lehetővé téve az egyszerű és nagyon robusztus API használatát. Az aszinkron funkciókat nem lehet megszakítani, és nincsenek fogalmuk az illékony tulajdonságokról, amikor különböző aszinkron hívásokkal kezeljük ugyanahhoz a változóhoz való hozzáférést. Az ES2017 aszinkron funkcióinak részletes megvalósítása nem tartozik a cikk hatálya alá, de a fő szempont, amellyel át szeretnék térni, az az, hogy mindeddig a párhuzamosságot nem építették be a Javascriptbe és az internetbe, és ezért nem kellett külön kezelni a ugyanazon entitás. De ez megváltozik a „Web Locks API” bevezetésével.
Egy mindenkiért és mindenki egyért
Most, hogy a progresszív webalkalmazások valódi, többszálú architektúrákat kínálnak a WebWorkers és a ServiceWorker bevezetésével, a dolgok megváltoztak. A webalkalmazásokban lehetséges az igazi párhuzamosság, ezért felmerül a vágy a kifinomultabb eszközök iránt a párhuzamos kód kezelésére.
A zár egy olyan mechanizmus, amely az erőforrásokhoz való hozzáférést kéri, és garantálja, hogy az idő bármely pontján csak egyetlen folyamat férhet hozzá. Az erőforrások ilyen módon történő zárolásával elkerülhetők a konfliktusterületek nagy sora, amelyek egyébként felmerülhetnek.
Az erőforrás csak egy névtér, amelyet egy karakterlánc azonosít. Az erőforráshoz való hozzáférés iránti kérelme ugyanolyan egyszerű, mivel a „Web Lock API” megvalósításához csak az azonosítóra és egy függvényhívásra van szükség, amely valószínűleg aszinkron. Amikor az egyik aszinkron funkció befejeződött, a zár felszabadul, és más kérelmek újra hozzáférhetnek hozzá.
/*
* A simple demonstration of the Web Lock API.
* Note that this example has been taken from
* MDN's awesome documentation, linked in the
* addendum.
*/
async function foo(){
// A common async function that you already know.
const data = await getData();
// Request the lock.
// Note that we can simply await the locked call!
await navigator.locks.request('lock_resource_id', async lock => {
// The lock has been acquired.
// At this point, this call has exlusive access
// to the resource 'lock_resource_id'.
await updateDb(data);
// Now the lock will be released.
});
// The lock has been released.
// Continuse with plain async calls.
await updateUi();
}
Ennek az új API-nak a kísérleti állapota miatt a kód opcionális szolgáltatásaként kell kezelnie, érvényes érvényes tartalékkal.
/**
* Due to the usage of web locks in core parts
* of your app, actually using the API this way
* might introduce more problems then it could solve.
*
* Therefore a thorough specification in your app
* has to be implementation before using this feature.
*/
async function update(){
if(navigator?.locks){
// Run logic with lock.
} else {
// Use fallback.
}
}
Az új API jobb szemléltetése érdekében megnézünk egy egyszerű példát. Tegyük fel, hogy van egy többszálú PWA a fő folyamatával és két webmunkás. Az alkalmazás egy IndexDB-t is használ, egyedi kóddal, amely szinkronizálja a változásokat az adatbázisba és a felhőből. Ebben a forgatókönyvben a „Web Lock API” használatával minden folyamat hozzáférést kérhet a meghatározott zárhoz az adatbázis módosításainak szinkronizálásához, ügyelve arra, hogy a hívás során ne fusson más mutáció.
Ne feledje, hogy a „Web Lock API” nem annyira egyetlen változó mutációját jelenti mellékhatások nélkül a webalkalmazásban (bár ez egyértelműen felhasználási eset lehet), hanem sokkal inkább a függvényhívások párhuzamos architektúrában történő kezelését, amely egyébként a negatív mellékhatások.
Sokkal többet kell tanulni
Ez a cikk csak az új "Web Locks API" bevezetését nyújtotta, amely jelenleg kísérleti állapotban van, és főleg a Chromium-alapú böngészők támogatják. Az API további lehetőségeket kínál, amelyek leírják itt, és érdemes megnézni őket.