browser.storage.local.remove (obj[obj][obj])

  • Ich bastle schon einige Zeit an einer Webextension für Firefox. Selbige speichert relativ viele Daten als Objekt:

    Code
    var cfg = {};
    	cfg.foo = {};
    var con = {};
    	con.foo.bar = {};
    	con.foo.bar.eins = "foobar";
    	con.foo.bar.zwei = "barfoo";

    Jetzt habe ich gerade versucht eine Funktion zu schreiben, die mir erlauben würde einzelne Unterobjekte (con.foo.bar.eins) zu löschen. Aber egal wie ich dieses Sub-Objekt an browser.storage.local.remove übergebe, ich bekomme es nicht hin.

    Nach einer (zugegeben kurzen) Google-Suche bin ich nur auf eine stackoverflow-Frage für Google Chrome gestossen, bei der es hiess, dass das so nicht funktionieren würde, da nur Top-Level IDs als Parameter akzeptiert würden. Ich müsste also das betreffende Top-Level-Objekt per get abrufen, das zu löschende Objekt entfernen und dann das gesamte Top-Level-Objekt wieder speichern (womit das Sub-Objekt ja weg wäre). Das könnte ich natürlich machen, aber... :traurig:

    Meine Fragen wären jetzt: Lässt sich obiges wirklich nicht anders lösen? Und wenn doch, könnte mich jemand auf ein Stück Beispielcode schubsen?

    Hinweis: Ich habe die Frage parallel in de.comm.infosystems.www gestellt, aber die Gruppe ist nicht gerade sonderlich gut benutzt wie es scheint.

    Greetz,
    DF

  • Kurzer Nachtrag:

    splice() hat auch nicht so ohne weiteres funktioniert. Ich hätte das Objekt erst in seine Bestandteile zerlegen müssen um es einzelnd zu entfernen. Aber man lernt ja nie aus:

    Code
    delete obj.objSub[zulöschendesObj]

    funktioniert wunderbar.

    Greetz,
    DF

  • delete ist in deinem Fall wirklich die bessere Wahl, weil du ein Objekt-Literal löschen möchtest, wenn ich mir dein Beispiel nochmal genauer ansehe. Mea culpa. In meinem Fall wurde ein Array-Element gelöscht. Ein kleiner, aber sehr wichtiger Unterschied.

    Erklärung:

    Bei mir heißt es ja:

    Code
    const { configurations } = await browser.storage.local.get({ configurations : [] });

    Die Syntax mit den geschweiften Klammern ist interessant. Das ist nämlich das Gleiche wie:

    Code
    const configurations = await browser.storage.local.get({ configurations : [] }).configurations;

    Das nennt man Object Destructuring. Ein einfacheres Beispiel dafür:

    Code
    const firstname = person.firstname;
    const lastname = person.lastname;
    const gender = person.gender;

    Wie man sieht, ist der Variablenname immer gleich des Namens der Objekteigenschaft. Lästig, diese Wiederholung. Seit EcmaScript 6 gibt es Object Destructuring, um es kürzer so zu schreiben:

    Code
    const { firstname, lastname, gender } = person;

    Lange Rede, kurzer Sinn: In meinem Beispiel weise ich der Variablen "configurations" die Eigenschaft "configurations" des Objektes zu, welches ich aus dem Storage lese, und das ist in meinem Fall ein Array, welches beliebig viele Konfigurationen beinhaltet, wie man in einem anderen Teil des Codes sieht. Eine andere Situation als bei dir.

    Möchtest du etwas komplett rauslöschen, gibt es im Prinzip eine einfache Grundregel:

    - Möchtest du ein Element aus einem Array löschen, verwende splice()
    - Möchtest du ein Objekt-Literal löschen, verwende delete

    Verwendest du delete auf ein Array, ist der Inhalt durchaus weg, aber du erzeugst einen leeren Slot an der gleichen Stelle und die Länge des Arrays bleibt gleich, was man in den meisten Fällen vermutlich nicht möchte:

    Code
    const x = ['a', 'b'];
    delete x[0];
    console.log(x.length)

    Das wird "2" und nicht "1" ausgeben.

    Verwendest du splice() auf ein Objekt-Literal bekommst du nur einen Syntax-Fehler, weil splice() eine Array-Methode ist.


  • Bei mir heißt es ja:

    Code
    const { configurations } = await browser.storage.local.get({ configurations : [] });

    Ich hatte drüber nachgedacht, die Daten auf der "ersten Ebene" zu speichern so wie bei dir oder auch bei EffPeh, also wirklich Arrays zu speichern statt ganzen Objekten. Aber das Problem ist da die Nutzerverwaltung. Ich trenne zwischen verschiedenen Nutzern des AddOns innerhalb eines Browser-Profils und durch die Möglichkeit verschiedene Anmeldungen pro Domain zu nutzen wächst das Gebilde um eine weitere Ebene. Ich müsste also immer den Nutzernamen und die jeweilige Identität mit in den Bezeichner stopfen um es trennen zu können. Das würde den Code für mich noch unübersichtlicher machen, bin halt nur Hobbybastler der sich den Kram selbst beibringt.

    Daher gibt es innerhalb des storage nur wenige "echte" Arrays und der Rest sind ziemlich verschachtelte Objekte. Der relative Nachteil ist, dass es am Ende einfacher ist immer den kompletten storage zu laden um Daten zu ändern statt nur einzelne Bereiche und halt die Tatsache, dass die Abfrage einzelner Subobjekte zu einem ziemlich langen Text führt. Ich werde noch testen müssen, in wie weit das zum Problem für die Geschwindigkeit wird wenn die Datenmenge wächst und das AddOn permanent Daten durch die Gegend schubst, aber da es zum Glück immer nur wenige Byte pro Eintrag sind, sollte das eigentlich kein Problem darstellen. Notfalls muss ich halt die Datenstruktur noch umstricken.

    Zitat


    Verwendest du splice() auf ein Objekt-Literal bekommst du nur einen Syntax-Fehler, weil splice() eine Array-Methode ist.

    Jepps, soweit habe ich das inzwischen auch kapiert. Ich kannte bis dato nicht einmal den Befehl "delete" :oops:, aber man lernt halt nie aus ;).

    Greetz,
    DF