在 Angular 中等待用户交互时,可替代延迟(反?-)模式
Posted
技术标签:
【中文标题】在 Angular 中等待用户交互时,可替代延迟(反?-)模式【英文标题】:Alternatives to Deferred (anti?-)pattern when awaiting for user interactions in Angular 【发布时间】:2021-11-05 15:48:35 【问题描述】:我正在使用具有以下机制的 Angular 构建游戏:
-
Angular 服务检查游戏状态并请求所需的用户交互。
中介服务创建此请求并使用 RxJS 主题将其发送到相关的 Angular 组件。
在此中介服务中等待对此请求的响应,直到请求得到解决,游戏才会继续。
组件通过调用
request.respond(response)
方法设置用户对请求的响应。
我需要提出一个适合此要求的 Request 类。由于请求一劳永逸地解决,我决定避免将其基于 RxJs Observable,而是尝试使用 javascript Promise。使用 async
/await
语法可以轻松地等待 Promise,而要求 (4) 让我了解了 the Deferred pattern。我为各种请求构建了这个基类:
abstract class Request<T>
private _resolve: (value: T) => void = () => ;
private _response: Promise<T> = new Promise<T>(resolve =>
this._resolve = resolve;
);
public get response(): Promise<T>
return this._response;
public respond(response: T)
this._resolve(response);
我没有添加拒绝处理,因为我没有想出请求可能失败的情况。似乎甚至不需要超时,因为游戏需要响应才能继续。
这非常适合我的目的,但后来我开始发现讨论将此视为反模式(例如,this 和 this)。我不习惯使用 Promise,所以我不完全理解暴露解析功能的风险,我无法辨别这种模式何时合法的情况,我也无法想象使用其他方式来满足我的要求承诺。
我想知道这是否是使用 Deferred 模式的合法方式,如果不是,是否有另一种方式来实现我所需要的。
【问题讨论】:
【参考方案1】:延迟反模式的问题不在于暴露resolve
函数本身,而在于暴露它与promise 一起(或更糟的是,作为promise 的一部分)。您的请求类没有理由需要包含承诺。相反,您需要做的只是
const response = await new Promise(resolve =>
mediator.send( respond: resolve );
);
中介者只需要这个对象,处理请求的组件仍然可以简单地调用request.respond(response)
。这比做简单得多
const request = new Request();
mediator.send(request);
const response = await request.response;
这可能是不必要的复杂(与Request
类中的所有代码),但使用还没有问题。它真正成为反模式的地方是如果你这样做了
function sendRequest()
const request = new Request();
mediator.send(request);
return request;
因为现在有人有一个“延迟对象”,而不仅仅是响应的承诺。他们可能会滥用该功能:
const request = sendRequest();
request.respond("Ooops");
const response = await request.response;
这是真正的危险:返回一个不应该解决承诺的延迟代码。将resolve
函数交给应该响应的组件是完全没问题的。
【讨论】:
我仍然需要派生的Request
对象,其中包含要在组件中显示的信息。如果将resolve
函数交给组件是安全的,我想我可以在promise 执行器中创建Request 实例,并使用resolve 函数作为参数,以便响应方法可以使用它:new Promise(resolve => mediator.send(new Request(data, resolve)); )
。
是的,完全正确 - 只需在构造函数中执行 this.respond = resolve
即可。我的意思是您也可以将data
放在对象文字中,但我假设您的class
有一些额外的方法,这些方法比您问题中代码中的promise getter 更有用:-)
感谢您的回答,它绝对简化了代码并澄清了延迟对象的问题!
事实上,只要简单的接口和对象字面量就可以了!以上是关于在 Angular 中等待用户交互时,可替代延迟(反?-)模式的主要内容,如果未能解决你的问题,请参考以下文章
让工作线程在 GUI 线程中等待用户输入? Python/PyQt
Angular CanLoad 防护仅在第一次延迟加载时触发一次?