ES6 обещания и свойства класса - PullRequest
1 голос
/ 17 марта 2019

Как любителю PHP-кода, мне трудно понять асинхронное поведение JS.Я пишу Firefox WebExtension, в котором для установки / получения параметров используются две StorageAreas из API-интерфейса хранилища, и я хочу объединить все параметры в один объект для эффективной передачи приложения:

'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 browser.storage. *. get () или связанный с областями действия переменных.

Я пытался:

  1. объявить локальную переменную в get *-functions (let that = this;)
  2. , использующий async / await в get * -functions
  3. , связывающий результат get * -functions с этим или this.defaults
  4. перед созданием этого класса я начал с вложенных Обещаний, но также я не смог создать (глобальную) переменную 'options'.

Спасибо за любые указатели - мой разум устал пересматривать/ переписываю эти 36 лока ...

Ответы [ 2 ]

1 голос
/ 17 марта 2019

Вы не ждете обещаний, созданных с помощью вызовов this.getDefaults(); и this.getLocals();, поэтому во время выполнения this.options = Object.assign( ... данные не готовы.

Если вы создаете обещание в функциизатем вам нужно вернуться из него, чтобы вызывающий мог дождаться разрешения этого Обещания.

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 должно быть закончено.

0 голосов
/ 17 марта 2019

Не пишите асинхронные функции для инициализации ваших экземпляров . Вместо этого выполните асинхронную работу перед построением объектов , и пусть конструктор примет данные в качестве параметров.

В вашем случае это

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 { … }
});
Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...