gpt4 book ai didi

Angular:检测昂贵的同步函数内部的变化

转载 作者:太空狗 更新时间:2023-10-29 19:33:23 26 4
gpt4 key购买 nike

我有一个执行昂贵的同步任务的函数。在我的例子中,它是通过 pdfkit 生成的客户端 pdf,但让我们用 while-loop sleep 来模拟它。

我想在运行任务之前显示一个“正在加载”微调器,并在完成后隐藏它。

如果一切都同步运行,Angular 将没有机会在一切结束之前运行变化检测循环,所以我认为我必须找到一种异步运行它的方法。

我试着把它包装在一个 promise 中,所以假设我有:

sleep(ms) {
return new Promise((resolve, reject) => {
const expire = (new Date()).getTime() + ms;
while ((new Date()).getTime() < expire);
resolve();
});
}

但是我是否使用 .then() 调用来运行它:

run() {
this.running = true;
this.sleep(2000).then(() => {
this.running = false;
});
}

或使用异步/等待:

async run() {
this.running = true;
await this.sleep(2000);
this.running = false;
}

在函数结束之前不会检测到更改,并且不会显示任何内容。

我猜问题是 Javascript 仍然是单线程的,并且 promise 仍然在创建时立即运行,所以一切基本上仍然同步运行。

但即使使用 ChangeDetectorRef.detectChanges() 强制更改检测也无济于事。

到目前为止我找到的唯一解决方案是在 setTimeout hack 中运行它:

setTimeoutRun() {
this.running = true;
setTimeout(() => {
this.sleep(2000);
this.running = false;
}, 100);
}

但它看起来不像是正确的正式解决方案。

setTimeout 真的是唯一的方法吗?

笨蛋:https://embed.plnkr.co/ywsIhulPMqjqwzaMxVjn/

最佳答案

如果您的作业是同步的,那么您的加载逻辑也需要同步。除了利用 setTimeout 的事件循环之外,没有其他方法(据我所知)。

换句话说,您不能执行类似this.loading = true 的操作,因为那将不得不等待更改检测运行。您必须显式启动加载逻辑(手动将加载器元素添加到 DOM 以使其立即可见,等等)。

否则,根据定义,它必须等到您的长同步作业完成后才能开始加载,因为加载器逻辑本身将是异步的,因此只会在当前执行(即您的同步作业)完成后调用.

例如:

@Component({...})
export class MyComponent implements OnInit {
constructor(private loadingService: LoadingService) {}

ngOnInit() {
// Start synchronous loader...
this.loadingService.start();

// By the time code reaches here, loader should be visible.

// Do expensive synchronous task...
this.expensiveSynchronousTask().then(() => {

// Stop synchronous loader...
this.loadingService.stop();

});
}
}

关于Angular:检测昂贵的同步函数内部的变化,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/49561109/

26 4 0
Copyright 2021 - 2024 cfsdn All Rights Reserved 蜀ICP备2022000587号
广告合作:1813099741@qq.com 6ren.com