Могу ли я разрешить обещание при изменении переменной без использования deferr? - PullRequest
0 голосов
/ 24 марта 2020

Я конвертирую некоторый код машинописи на основе Q-обещаний в обещания ES6.

В определенный момент я использовал Q.defer, и в своей миграции я просто переписал defer как обещание ES6, как описано в этом комментарий: { ссылка }

Я пытался избавиться от этого отложенного подхода, если возможно, и искал альтернативные решения.

Причины моего вопроса:

  1. Отложенные обещания считаются анти-паттерном, в общем
  2. Хотите знать, является ли этот сценарий одним из немногих, где отсрочка действительно единственный путь

Вот мой сценарий:

// app start, this is my low level API
init() {
    commService.subscribe("myRecordId", {
        onRecordAdd: this.onAdd
    });
}

...

private _myRecord: MyRecordObj | null = null;
private _recordReceivedDef = newDeferred(); // was Q.defer()

// callback will be called when record is received
private readonly onAdd = (recordObj: MyRecordObj) => {
    this._myRecord = recordObj;
    this._recordReceivedDef.resolve(recordObj);
}

...

// here's my async code that requires the deferred
public readonly doStuff = async () => {
    // ...
    const myRec = await this._recordReceivedDef.promise;
    // use myRef
}

Мой вопрос: Есть ли способ, которым я могу избавиться от этой отсрочки? Я думал о чем-то, что разрешается при изменении _myRecord , но не знаю, как это сделать.

Примечание: я использую MobX в других частях нашего приложения, поэтому было бы удобно иметь

await when(() => this._myRecord); // of course _myRecord must be @observable

, но, к сожалению, я не могу использовать MobX в этом конкретном куске кода.

Любая помощь очень оценил.

Большое спасибо!

1 Ответ

0 голосов
/ 24 марта 2020

Если предположить, что init вызывается раньше doStuff, правильный путь будет

init() {
    this._myRecordPromise = new Promise((resolve, reject) => {
        commService.subscribe("myRecordId", {
            onRecordAdd: (recordObj: MyRecordObj) => {
                // callback will be called when record is received
                resolve(this._myRecord = recordObj);
            }
        });
    });
}

…

private _myRecord: MyRecordObj | null = null;
private _myRecordPromise: Promise<MyRecordObj>;

…

public readonly doStuff = async () => {
    …
    const myRec = await this._myRecordPromise;
    // use myRef
}

. Вы можете даже полностью сбросить _myRecord и оставить только _myRecordPromise.

* 1009. * Тем не менее, вы можете захотеть вообще не создавать свой экземпляр до получения записи, см. Это плохая практика, когда функция-конструктор возвращает Promise? .

Если init вызывается в произвольное время, вам понадобится какой-то шаблон отсрочки, но вам не нужно newDeferred() для этого. Просто напишите

init() {
    commService.subscribe("myRecordId", {
        onRecordAdd: this.onAdd
    });
}

…

private _myRecordPromise: Promise<MyRecordObj> = new Promise(resolve => {
    this.onAdd = resolve;
});
private readonly onAdd: (recordObj: MyRecordObj) => void;
...