As an amateur PHP coder, I'm having a hard time grasping JS async behavior. I'm writing a Firefox WebExtension that uses two StorageAreas from the Storage API for setting/getting options, and I want to merge all options into one object to pass around the application efficiently:
'use strict';
class Options {
constructor() {
this.defaults = {};
this.locals = {};
this.options = {};
}
getDefaults() {
browser.storage.managed.get().then(res => {
this.defaults = res;
});
}
getLocals() {
browser.storage.local.get().then(res => {
this.locals = res;
});
}
get() {
this.getDefaults();
this.getLocals();
this.options = Object.assign(this.defaults, this.locals); // <-- This is where the code fails: this.defaults and this.locals are empty.
return this;
}
}
const opts = new Options().get();
console.log(opts); // Object { defaults: {}, locals: {}, options: {} } background.js:31:1
console.log(Object.keys(opts)); // Array(3) [ "defaults", "locals", "options" ] background.js:32:1
console.log(opts.defaults); // Object { } background.js:33:1
const options = Object.assign(opts.defaults, opts.locals);
console.log(options); // Object { } background.js:36:1
I have indicated the line where the error first triggers, and after banging my head against the same wall for 2+ days now, I believe it is either related to the async character of the Promise returned by Firefox's browser.storage.*.get(), or related to variable scopes.
I have tried:
- declaring a local variable in the get*-functions (let that = this;)
- using async/await in the get*-functions
- binding the get*-functions' result to either this or this.defaults
- before creating this class, I started with nested Promises, but also then I was unsuccesful in creating a (global) 'options' variable.
Thx for any pointers - my mind is tired of reviewing/rewriting these 36 loc...