[Solved] Browser storage sync get return undefined

Hi, I’m trying to make an add-on for Firefox that will store some values which will be used later on in an contextMenus.

Getting the value and setting a new one in options_ui works just fine. The problem is when I try to get the value by using the new contextMenu I am adding in background.js. The new contextMenu it is added, the window for saving the file appers, but the value from storage returns undefined . Can anyone help me with this, point me where I’m doing something wrong?
I am setting a new value before using the contextMenu.

background.js

var gettingValue = browser.storage.sync.get("number");
gettingValue.then(item =>{
	browser.contextMenus.create({
		id: "save-image",
		title: "Save image",
		contexts: ["image"],
	});

	browser.contextMenus.onClicked.addListener((info, tab) => {
		if (info.menuItemId === "save-image") {
			let name = "Initial";
			if(item) {
				name = item.number;
			} else {
				name = "Number not found";
			}
			browser.downloads.download({
				url : info.srcUrl,
				filename : name + ".jpg",
				saveAs : true
			});
		}
	});
});

options.js

function saveOptions(e) {
	e.preventDefault();
	browser.storage.sync.set({
		number: document.querySelector("#newNumber").value
	});
}

function restoreOptions() {
	let getting = browser.storage.sync.get("number");
	getting.then(setCurrentChoice, onError);

	function setCurrentChoice(result) {
		document.querySelector("#newNumber").value = result.number || "No number was set";
	}

	function onError(error) {
		console.log(`Error: ${error}`);
	}
}

document.addEventListener("DOMContentLoaded", restoreOptions);
document.querySelector("form").addEventListener("submit", saveOptions);

options.html

<!DOCTYPE html>
<html>
  <head>
    <meta charset="utf-8">
  </head>
  <body>
    <form>
        <label>Number input: <input type="text" id="newNumber" ></label>
        <button type="submit">Save</button>
    </form>
    <script src="options.js"></script>
  </body>
</html>

Permissions in manifest

"permissions": [
    "contextMenus",
    "downloads",
    "storage"
],

You are reading the value in your background script from the sync storage when your extension is loaded. However, the options page changes the value in the sync storage after the extension is loaded.

To solve this, get the value at the time that you actually use it in the listener in your background script.

You are reading the value in your background script from the sync storage when your extension is loaded. However, the options page changes the value in the sync storage after the extension is loaded.

I understood this part, and now it make sense why I was getting the old value when I was reloading the add-on.

To solve this, get the value at the time that you actually use it in the listener in your background script.

I am sorry but unfortunately this is my first try at making an add-on, and I didn’t really get what you mean by this. I thought the code from background.js is called each time I’m pressing that contextMenu I added, but it seems I was wrong about it. I tried adding the whole code from background into a function with some small changes, and added at the end the following line to kinda mirror the way it is done in options.js, but that didn’t work.

document.addEventListener("DOMContentLoaded", getValueInMenu);

Only code in the function passed to browser.contextMenus.onClicked.addListener is run every time. So you want to have the browser.storage.sync.get() and handling of the returned promise (the .then) inside that listener function.

Only code in the function passed to browser.contextMenus.onClicked.addListener is run every time. So you want to have the browser.storage.sync.get() and handling of the returned promise (the .then ) inside that listener function.

I really thought I tried it this way once before and it still didn’t worked, but maybe I’ve done something else wrong that time.

Thank you! The fix was really easy.

browser.contextMenus.create({
	id: "save-image",
	title: "Save image",
	contexts: ["image"],
});

browser.contextMenus.onClicked.addListener((info, tab) => {
	if (info.menuItemId === "save-image") {
		var gettingValue = browser.storage.sync.get("number");
		gettingValue.then(item =>{
			let name = "Initial";
			if(item) {
				name = item.number;
			} else {
				name = "Number not found";
			}
			browser.downloads.download({
				url : info.srcUrl,
				filename : name + ".jpg",
				saveAs : true
			});
		});
	}
});