v2.5.2
Giriş yap

chrome.storage.local fiyaskosu

munzevi
502 defa görüntülendi ve 2 kişi tarafından değerlendirildi

merhaba,

bir borsa eklentisi yazıyorum. normalde sunucuda yapacaktım, ama kişi tarayıcı eklentisini tercih etti. sinirden beynimden vurulmuşa döndüm.

standart localStorage kullanımını bilmeyen yoktur herhalde

let lSet = (name, value) => localStorage.setItem(name, value),
    lGet = name => localStorage.getItem(name);

ne güzel sade kısa öz, kullanılabilir. üstelik boolean türünde veride döndürüyor sorguladığınızda

var data = localStorage.getItem('data') ?
    localStorage.getItem('data') :
localStorage.setItem('data', 'data verisi');

sorguladım varsa seç, yoksa oluştur öyle seç dedim. pratik. ister döngüye al kullan, ister bir tane kullan

data.obj.forEach(([key => val]) =>{
    localStorage(key, val);
});

bir anda yüzlerce bile oluşturabildim. peki google napmış? bu güzelim yöntemi eklentiler için devre dışı bırakmış,

let data = {},
    lSet = (name, value) => {
        chrome.storage.local.set({[name]: value}, function() {
            data[name] = value;
        });
    },
    lGet = name => {
        chrome.storage.local.get([name], function(result) {
            return result.key;
        });
    },

hadi al sok bunu döngüye. değerin ne olduğu, nereye gittiği belli değil. bu kadar yorucu bi yöntem olur mu ya, hammallık resmen bu. arkadaş ben niye yöntem yazıp, içerisinde callback olarak tanımlama yapmak zorundayım. standart kullanımın yalın haliyle bile, ayarların konfigürasyonu ve verilerin çerez olarak depolanması için 479 satırlık sınıf yazdım. bu şekilde yaparsam, çoğu veriyi döngüye alamam uygun değil. çoklu dil desteğinden, çok sayıda form elemanlarının ayarına kadar veriyi localStorage de tuttum. tutmak zorundayım çünkü statik bir veri yok ortada. ne yapayım şimdi ben, iptal mi edeyim siparişi? hayır en çok zoruma giden? niye yani niye niye neşter dururken döner bıçağıyla ameliyata yolluyor beni google. set ettiğim değeride geri alamıyorum bu arada, anca get içerisinde calback yapacağım orda da kullanmak istediğim veriyle değişkeni eşitleyeceğim.

lütfen birileri benim görmediğim olumlu bir tarafını görüyorsa bu durumun, bana da göstersin.

ebykdrms
868 gün önce

Adım adım işlemleri okuduğumda şöyle bir işleyiş gördüm:
1) Sınıftan nesne oluşturduğunuz anda kurucu fonksiyon çalışıyor.
2) conf = {} ataması yapıyorsunuz.
3) storageData() fonksiyonunu çağırarak data = { lang: 'en', testData1: 1, testdata2: 2 } işlemini sağlyorsunuz.
4) datadaki veriyi Object.entries() işlevinden geçirip şu diziyi elde ediyorsunuz:
[ ["lang", "en"], ["testData1", 1], ["testData2", 2] ]
5) forEach() ile bu dizi üzerinde dönmeye başlıyorsunuz. Döngüyü adım adım işlersek:
5.1) key="lang" ve val="en" iken chrome.storage.local.get("lang", (obj) => {...}) işlevini çağırıyorsunuz. Bu asenkron bir fonksiyon olduğu için henüz sonuçlanmadan döngünün 2.adımına geçiyorsunuz.
5.2) key="testData1" ve val=1 iken chrome.storage.local.get("testData1", (obj) => {...}) işlevini çağırıyorsunuz. Bu asenkron bir fonksiyon olduğu için henüz sonuçlanmadan döngünün 3.adımına geçiyorsunuz.
5.3) key="testData2" ve val=2 iken chrome.storage.local.get("testData2", (obj) => {...}) işlevini çağırıyorsunuz. Bu asenkron bir fonksiyon olduğu için henüz sonuçlanmadan döngünüz bitiyor.
6) Döngü bitti. Henüz asenkron fonksiyonlar sonuç döndürmedi. Yani getData2() fonksiyonu çalışmadığı için henüz conf.lang değeri de dolmadı.
7) conf.now key'ini doldurduğunuz sırada henüz conf.lang key'i tanımlanmadı.
console.log(this.conf, this.conf.lang) sizi yanıltıyor. İlk parametrede obje, ikinci parametrede string gönderdiğiniz için, javascript de objelere ve string'lere farklı yaklaşımlar sergilediği için size yanıltıcı sonuçlar gösteriyor.
console.log() fonksiyonu okunduğu andan ekrana basma işlemini gerçekleştirene kadar geçen sürede this.conf.lang değeri dolmuş oluyor.
Yani console.log(this.conf, this.conf.lang) komutunu verdiğiniz anda şunu söylemiş oluyorsunuz: console.log(obje, "string")
Ekrana basılma sırasında console.log() string değeri doğrudan hafızasında tutarken, ilk parametredeki objenin sadece referansını tutuyor. Bu yüzden ekrana basılırkenki string değer gerçekten console.log() komutu ilk çağırıldığındaki değer olurken obje değeri ekrana basılma anındaki değer neyse o oluyor.
Eğer objenin de o andaki değerini almak istiyorsanız komutu şu şekilde düzeltmelisiniz:
console.log(JSON.stringify(this.conf), this.conf.lang); Böylece iki parametrede de string değer aldığı için çağırıldığı andaki değerler neyse onu yazdıracaktır.

Yani sizin obje olarak basınca değer var ama direkt değeri basınca değer yok olarak bahsettiğiniz olay javascript'in objeleri tutuş biçimindeki yaklaşımından kaynaklanıyor. (Ki aslında bu tutuş biçimi javascript'in yüksek performanslı olmasını sağlayan en büyük etkenlerden biri)

Sorunun çözümü olarak, emin değilim ama, conf.now key'ine değer atama işlemini callback fonksiyonunun içinde yapmanız gerekiyor olabilir.
Yani:

constructor() {
    this.conf = {};

    Object.entries(this.storageData().data).forEach(([key, val]) => {
        chrome.storage.local.get(key, obj => {
            if(!obj[key]) chrome.storage.local.set({[key]:val}, this.getData2({[key]:val}));
            else this.getData2(obj);
            
            if(key=="lang") {
                this.conf.now = new Intl.DateTimeFormat(this.conf.lang, {
                    weekday: 'long',
                    year: 'numeric',
                    month: 'long',
                    day: 'numeric',
                    hour: '2-digit',
                    minute: '2-digit',
                    second: '2-digit',
                    timeZoneName: 'longGeneric',
                    timeZone: this.conf.timeZone
                }).format(new Date(Date.now()));
                
                console.log("in callback: ", JSON.parse(JSON.strinify(this.conf)), this.conf.lang);
            }
        });
    });
    
    console.log("in constructor: ", JSON.parse(JSON.strinify(this.conf)), this.conf.lang);
}