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?
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?
-
10
Like most Chrome APIs,
chrome.storage.get
/set
are asynchronous. I've written an explanation of this in easy terms, which can be found here. – Rob W Commented Sep 3, 2012 at 21:11 - Thank you for that answer. That's a very good explanation . However, I really want to ues 'css' outside the callback function. Is there any way to to so? – user1597243 Commented Sep 4, 2012 at 14:23
- No. You cannot turn an asynchronous function in a synchronous function without changing the flow of your application. – Rob W Commented Sep 4, 2012 at 17:59
1 Answer
Reset to default 5I 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 bine 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 pletes 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 plex 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