作为一名业余PHP程序员,我很难掌握JS异步行为。我正在编写一个Firefox WebExtension,它使用来自Storage API的两个StorageAreas来设置/获取选项,并且我想将所有选项合并到一个对象中以有效地传递应用程序:
'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
我已经指出了错误首先触发的那一行,现在我的头撞到同一堵墙超过2天,我相信这与Firefox浏览器返回的Promise异步字符有关。*。 .get(),或与变量范围相关。
我尝试过:
感谢所有指针-我的主意是厌倦了查看/重写这36个位置...
答案 0 :(得分:1)
您不必等待呼叫this.getDefaults();
和this.getLocals();
所创建的承诺,因此在您进行this.options = Object.assign( ...
时,数据尚未准备就绪。
如果在函数中创建一个Promise,则需要从中返回,以便调用者可以等待该Promise解决。
getDefaults() {
return browser.storage.managed.get().then(res => {
this.defaults = res;
});
}
getLocals() {
return browser.storage.local.get().then(res => {
this.locals = res;
});
}
get() {
return Promise.all([
this.getDefaults(),
this.getLocals()
])
.then(() => {
this.options = Object.assign(this.defaults, this.locals);
return this
})
})
您当然还需要在then
上使用await
或get()
来等待get
完成。
答案 1 :(得分:0)
Don't write asynchronous functions to initialise your instances。相反,在构造对象之前 进行异步工作,让构造函数将数据作为参数。
就您而言,就是
class Options {
constructor(defaults = {}, locals = {}) {
this.defaults = defaults;
this.locals = locals;
this.options = Object.assign(this.defaults, this.locals);
}
// static methods that don't modify an instance, but return promises
static getDefaults() {
return browser.storage.managed.get();
}
static getLocals() {
return browser.storage.local.get();
}
// static method to load data and create an instance, returning a promise for it
static async get() {
const [defaults, locals] = await Promise.all([this.getDefaults(), this.getLocals()]);
return new this(defaults, locals);;
}
}
const options = Options.get();
console.log(options); // Promise { }
options.then(opts => {
console.log(opts); // Options { defaults: {…}, locals: {…}, options: {…} }
console.log(Object.keys(opts)); // Array(3) [ "defaults", "locals", "options" ]
console.log(opts.defaults); // Object { … }
});