我可以在不使用 deferr 的情况下在变量更改时解决承诺吗?
Can I resolve a promise when a variable change without using deferr?
我正在将一些基于 Q-promise 的打字稿代码转换为 ES6-promises。
在某个时候,我使用了 Q.defer 并且在我的迁移中我只是将 defer 重写为 ES6 promise,就像这条评论中解释的那样:
如果可能的话,我试图摆脱这种延迟方法,并且正在寻找替代解决方案。
我提问的原因是:
- 延迟承诺通常被认为是一种反模式
- 想知道这种情况是否是少数真正只有延迟的情况之一
这是我的场景:
// 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。
非常感谢任何帮助。
非常感谢!
假设 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
。
但是,您可能要考虑在收到记录之前根本不构建您的实例,请参阅 Is it bad practice to have a constructor function return a 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;
对于可能感兴趣的人,还有另一种使用事件发射器方法的解决方案。
假设您有一个 class EventEmitter 实现了以下接口:
// pseudo code
type UnsubscribeFn = () => void;
interface IEventEmitter<T> {
/** Fires an event */
emit(args: T): void;
/** Subscribes to emissions of this event and provides an unsubscribe function */
subscribe((args: T) => void): UnsubscribeFn;
}
您可以为您的客户提供如下所示的 whenAdded
功能
// pseudo code
class Subscriber {
readonly onAddEmitter = new EventEmitter<MyRecordObj>();
// app start
init() {
commService.subscribe("myRecordId", {
onRecordAdd: this.onAdd
});
}
onAdd = (rec: MyRecordObj) => {
// do some stuff
onAddEmitter.emit(rec);
}
whenAdded(): Promise<MyRecordObj> {
return new Promise((res) => {
const unsub = onAddEmitter.subscribe((record: MyRecordObj) => {
unsub();
res(record);
});
});
}
}
实现的目标是:
- 摆脱 Q promise,转而使用 ES6
- 使
commService
事件 API 适应基于承诺的事件
我正在将一些基于 Q-promise 的打字稿代码转换为 ES6-promises。
在某个时候,我使用了 Q.defer 并且在我的迁移中我只是将 defer 重写为 ES6 promise,就像这条评论中解释的那样:
如果可能的话,我试图摆脱这种延迟方法,并且正在寻找替代解决方案。
我提问的原因是:
- 延迟承诺通常被认为是一种反模式
- 想知道这种情况是否是少数真正只有延迟的情况之一
这是我的场景:
// 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。
非常感谢任何帮助。
非常感谢!
假设 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
。
但是,您可能要考虑在收到记录之前根本不构建您的实例,请参阅 Is it bad practice to have a constructor function return a 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;
对于可能感兴趣的人,还有另一种使用事件发射器方法的解决方案。 假设您有一个 class EventEmitter 实现了以下接口:
// pseudo code
type UnsubscribeFn = () => void;
interface IEventEmitter<T> {
/** Fires an event */
emit(args: T): void;
/** Subscribes to emissions of this event and provides an unsubscribe function */
subscribe((args: T) => void): UnsubscribeFn;
}
您可以为您的客户提供如下所示的 whenAdded
功能
// pseudo code
class Subscriber {
readonly onAddEmitter = new EventEmitter<MyRecordObj>();
// app start
init() {
commService.subscribe("myRecordId", {
onRecordAdd: this.onAdd
});
}
onAdd = (rec: MyRecordObj) => {
// do some stuff
onAddEmitter.emit(rec);
}
whenAdded(): Promise<MyRecordObj> {
return new Promise((res) => {
const unsub = onAddEmitter.subscribe((record: MyRecordObj) => {
unsub();
res(record);
});
});
}
}
实现的目标是:
- 摆脱 Q promise,转而使用 ES6
- 使
commService
事件 API 适应基于承诺的事件