Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

How chrome.storage.local.get sets a value?

var storage = chrome.storage.local;
var css = "old";
storage.set({'css': 'new'});
storage.get('css', function(items) {
    if (items.css) {
        css = items.css;
        console.log(css);
    }
});
console.log(css);

I am trying to upgrade my chrome extension to fit the manifest version 2.
While I run the code above, I get the first console.log returns "new" and the second one returns "old". How can I get two "new" if I want to set css to a new value?

like image 313
user1597243 Avatar asked Sep 03 '12 18:09

user1597243


1 Answers

I will explain why you are getting that behavior and how to fix.

This is your code:

var storage = chrome.storage.local;
var css = "old";
storage.set({'css': 'new'});
storage.get('css', function(items) {
  if (items.css) {
    css = items.css;
    console.log(css);
  }
});
console.log(css);

First of all you should know that by design, most of javascript API (at least from browser) accesing I/O is asynchronic , this include the chrome.storage API because it access a DB/filesystem or something implying I/O operations

Second, the Javascript code combine both, synchronous and asynchronous code running, hence the confusion

Asynchronous code runs on JS EventLoop , always after your synchronous code (there is no threads on JS), so, in your code, 5 always will run before 6:

var storage = chrome.storage.local; // 1
var css = "old"; // 2
storage.set({'css': 'new'}); // 3
storage.get('css', function(items) {
  // 6. this only will run AFTER this synchronous code returns
  if (items.css) {
    css = items.css;
    console.log(css);
  }
}); // 4
console.log(css); // 5. this always run before ANY callback

In fact there is chance of things running before 6 and after 5 (depending on how fast the I/O operation completes and invoke your callback)

Now, the solution

You need to do in the callback whatever you want to do with the retrieved info, this style of programming you can like it or not, but it is the JS way (soon as the code turns more complex and consume more I/O api you will be worried about callback hells and it can be addressed using Promises/Deferred, but that's another matter)

var storage = chrome.storage.local; // 1
// var css = "old"; // 2
storage.set({'css': 'new'}); // 3
storage.get('css', function(items) {
  // 5. this only will run AFTER this synchronous code returns
  if (items.css) {
    var css = items.css; // this variable belongs to this scope
    // do here whatever you need with the retrieved info
    // since it is CSS, maybe you want to create a new stylesheet of that (is only an example)
    var style = document.createElement("style");
    style.innerText = css;
    document.head.appendChild(style);
  }
}); // 4
// console.log(css); // can't access css here, is synchronous and it runs before the callback
like image 139
dseminara Avatar answered Oct 03 '22 12:10

dseminara