несколько `asyn c getter (s)` в одном объекте, действующем как кеш - PullRequest
0 голосов
/ 17 февраля 2020

Update2: Следующее работает, но не совсем

const obj = {
    cached_a: 0,
    cached_b: 0,
    cached_c: 0,

    get a() {
        if (this.cached_a == 0) this.cached_a = getA();
        return this.cached_a;
    }
}

const getA = function() {
    console.log('calcing...')
    return 25;
};

console.log('1: ' + obj.a);
console.log('2: ' + obj.a);

В моей программе значение не рассчитывается второй раз, а отправляется обратно из кэша.

$ node get-set.js 
calcing...
1: 25
2: 25

Например, мой getA() должен быть async. Но я понимаю, что ES6 не позволяет async getters. Если это правильно, я был бы признателен за лучший способ достижения вышеуказанного (учитывая, что getA() имеет , чтобы быть async.

Во-вторых, как мне использовать несколько getters (также для b и c)?


Update1: getA() (и, надеюсь, другие получатели) получают значения с сервера (это все браузер), и я не хочу, чтобы это происходило, если значение было получено один раз и кэшировано в браузере.


Я пытаюсь понять и реализовать getter/setter в объекте, который собирается выступать в качестве кэша для значений, возвращаемых async процессами.

'use strict';

// my desired pseudo-object with incorrect code
const obj = {
    a: 0,
    b: 0,
    c: 0,

    get a() {
        if (this.a == 0) this.a = await getA();
        return this.a;
    }

    get b() {
        if (this.b == 0) this.b = await getB();
        return this.b;
    }

    get c() {
        if (this.c == 0) this.c = await getA();
        return this.c;
    }
};

const getA = async function() { … };
const getB = async function() { … };
const getC = async function() { … };

Очевидно, что некоторые проблемы, описанные выше:

  • не могут иметь несколько getters (или я могу?);
  • не может иметь имя getters, совпадающее со свойством, так как это приводит к рекурсивному вызову (как мне сделать процесс прозрачности для пользователя?)

Как лучше это реализовать?

1 Ответ

0 голосов
/ 17 февраля 2020

Есть несколько способов сделать это, но рискуя помочь вам с проблемой, которой у вас нет (я подозреваю, что ваш общий дизайн приложения имеет fl aws, вы должны исправить в другом месте), я обращусь к вашему Немедленная проблема.

Ваши ошибки коренятся в том факте, что описания вашего свойства - будь то, например, a: 1 или get a() ..., используют один и тот же дескриптор свойства (обычно называемый «имя»), так что ваш получатель переопределяет то, к чему относится, например, this.a, перезаписывая предыдущее описание свойства (a: 1), и то же самое относится к другим свойствам b и c.

Я также хочу заявить, что ваше очевидное Идея кэширования обещаний заставляет меня думать, что, возможно, некоторые из ваших предположений неверны - когда обещание разрешается, значение уже кэшируется внутри. Обещание предназначено для расчета (разрешено или отклонено) только один раз, но каждый раз, когда вы присоединяете обратный вызов, хотя Promise.prototype.then, обещание [урегулированное] будет вызывать ваш обратный вызов с внутренним кэшированным значением. await - это немного больше, чем просто syntacti c, когда интерпретатор внутренне выполняет ваш код по порядку, но будьте уверены, что при вычислении выражения await будет использовано кэшированное значение, которое было "разрешено" однажды.

Я пытаюсь вам сказать, что кэширование обещаний не имеет смысла.

То, что вы можете кешировать, - это оценка процедуры. Вы начинаете с предположения, что вызов процедуры (без аргументов, чтобы упростить кэширование) всегда будет возвращать то же значение, которое вы затем можете безопасно связать с процедурой, в вашем кэше:

const cached = (() => {
    const cache = new WeakMap();
    return (procedure) => {
        var result = cache.get(procedure);
        return result || (cache.set(procedure, result = procedure()), result);
    }
})();

Теперь, если у вас есть дорогостоящая операция, инкапсулированная в функцию, скажем, request_foobar, вместо использования выражения request_foobar(), которое будет выполнять длительную операцию, каждый раз возвращающую один и тот же результат, вы можете использовать выражение cached(request_foobar()), которое даст вам предыдущий результат из кэша, если есть попадание в кеш, или, если его нет, вызовите процедуру и верните кэшированный результат.

Реализация cached зависит от так называемого «закрытия» функции - процедура, присвоенная константе cached, может обращаться к объектам (переменным, константам и т. д. c) во внешней области, включая фактический кэш (карту результатов, основанную на ссылках на процедуры).

...