等待点击 Promise 完成的 Angular 指令
Posted
技术标签:
【中文标题】等待点击 Promise 完成的 Angular 指令【英文标题】:Angular directive that waits for click Promise to complete 【发布时间】:2019-07-08 15:09:56 【问题描述】:更新 1:根据@PierreDuc 的回答,我在这里分叉并创建了一个更简单的版本:Simplified Example。伙计,我记得在 AngularJS 中能够完全劫持(点击)函数并执行它。我明白了,我明白了,不过我喜欢下面的简化提案。那应该对我有用:)
我创建了一个 Angular 按钮指令,它接受一个方法作为 Promise。 单击时,我禁用该按钮。当 Promise 解决后,我会重新启用该按钮。
基本上,在单击时,我想禁用该按钮,直到该按钮事件正在执行的所有处理完成,包括任何 http 调用。
我已经完成了我在这里看到的目标:Stackblitz Example。
我不是特别喜欢我的“解决方案”。
这太复杂了。为了让它发挥作用,需要发生三件事。
-
指令被添加到按钮。
设置“waitFor”属性。
“waitFor”函数必须是返回 Promise 的函数。
IMO,需要调整的东西太多了。
我真正想做的是获取按钮的 (click) 方法的句柄,并在指令中手动执行它,就像我执行“waitFor”属性的方式一样。
我该怎么做?
至少,我想要一个不需要指令名称(“appClickWait”)和属性(“[waitFor]”)的指令。
为方便起见,这里是代码:
指令:
import Directive, HostListener, ElementRef, Output, Input, EventEmitter, Renderer2 from '@angular/core';
// Enfore this directvie can only be used on a button?
@Directive(
selector: '[appClickWait]'
)
export class ClickWaitDirective
@Input("waitFor") clickWait: any;
constructor(private el: ElementRef, private renderer: Renderer2)
@HostListener('click', ['$event'])
clickEvent(event)
event.preventDefault();
event.stopPropagation();
this.renderer.setAttribute(this.el.nativeElement, 'disabled', 'disabled');
const originalInnerText = this.el.nativeElement.innerText;
this.el.nativeElement.innerText = 'Processing...';
const reset = () =>
this.renderer.removeAttribute(this.el.nativeElement, 'disabled');
this.el.nativeElement.innerText = originalInnerText;
;
// I really would like to just get a handle on the (click) function here
// that would greatly simplify the useage of this directive
this.clickWait()
.then((data) =>
reset();
)
.catch(err =>
console.error(err);
reset();
);
模板:
myClickFunc = async () =>
console.log('start')
this.posts = [];
// too fast, let's wait a bit
// this.posts = await this.http.get('https://jsonplaceholder.typicode.com/posts').toPromise();
await new Promise((resolve, reject) =>
setTimeout(async () =>
try
this.posts = await this.http.get('https://jsonplaceholder.typicode.com/posts').toPromise();
catch (err)
reject(err);
resolve();
, 1000);
);
console.log('all done');
<button type="button" appClickWait [waitFor]="myClickFunc">Single Wait Click</button>
谢谢!
【问题讨论】:
【参考方案1】:我想您可以将其简化为:
@Directive(
selector: 'button[appClickWait]'
)
export class ClickWaitDirective
@HostBinding('disabled')
public waiting = false;
@Input()
appClickWait: () => Observable<any> | Promise<any> = async() => void 0;
@HostListener('click')
clickEvent()
this.waiting = true;
from(this.appClickWait()).pipe(take(1)).subscribe(
subscribe: () => this.waiting = false,
complete: () => this.waiting = false,
error: (e) =>
console.error(e);
this.waiting = false;
)
这种用法:
<button [appClickWait]="myClickFunc">Single Wait Click</button>
myClickFunc = () => this.callHttp();
这样它只能在一个按钮上工作。 disabled 属性将自动设置,您可以插入一个返回 promise 或 observable 的函数。
stack;
【讨论】:
非常感谢您的回复!这确实是一个更简单的用法。我也从你的例子中学到了一些东西,所以 TYVM。我应该对此感到高兴,但是,作为开发人员,我想让它变得更简单,哈哈 :) 工作示例:stackblitz.com/edit/… @user1949561 我已经稍微简化了你的堆栈。链接在答案的底部。我不知道它应该变得更简单:)。您从该指令收到的每个请求都是一行。另外建议,在 99.9& 的情况下,您不应该使用渲染器。它的棱角分明。 爱它,再次非常感谢!啊,'禁用',我喜欢想象我会迭代直到我意识到:P以上是关于等待点击 Promise 完成的 Angular 指令的主要内容,如果未能解决你的问题,请参考以下文章
Promise.all 的 then() 函数在 Promise 完成之前执行 - Ionic/Angular
Javascript等待Promise在返回响应之前完成for循环