【问题标题】:How to start an anonymous asynchronous function in Angular 2/4?如何在 Angular 2/4 中启动匿名异步函数?
【发布时间】:2017-09-08 17:06:25
【问题描述】:

在我的 Angular 4 组件中,我有一个排序方法。它实际上就像单击表的标题并按该列更改排序顺序以及升序/降序一样简单。但是,那里有一个对服务的调用,最终可能会变得非常昂贵,所以我试图使这个调用异步。示例:

sortColumn(): void {
    this.service.someExpensiveBlockingOperation();
    this.sortOrder = !this.sortOrder;
    this.data.sort((a, b) => { ... });
}

我尝试过使用 Promises 和 Observables,以及 Async / Await,但没有成功。我觉得我错过了一些东西,因为 JS 应该是一种非阻塞、异步驱动的语言。

【问题讨论】:

  • 你说的“匿名异步函数”是什么。这与问题有什么关系?你认为你可以从异步调用中获得什么?难道this.data.sort()不应该等待this.service.someExpensiveBlockingOperation()完成?
  • 没错。我希望someExpensiveBlockingOperation() 开始,然后立即转到下一行代码。昂贵的操作基本上是用户不需要知道的后端调用,并且不应该等待该调用完成以更新视图。

标签: javascript angular typescript asynchronous nonblocking


【解决方案1】:

因为 JS 应该是一种非阻塞、异步驱动的语言

不,不是。但我们通常在倾向于异步的环境中使用它。 JavaScript 基本上就像任何其他语言一样,代码一步一步地同步进行。 JavaScript 本身的唯一异步的东西,与我们运行它的环境相反,是 Promise 和围绕它们的语法,例如 async/await

如果您想让您的排序调用相对于触发器是异步的,那么查看 Promise 是正确的:

sortColumn(): void {
    this.sortOrder = !this.sortOrder;
    Promise.resolve().then(() => {
        this.service.someExpensiveBlockingOperation();
        this.data.sort((a, b) => { ... });
    });
}

我已经在同步代码中放置了标志翻转,在异步回调中放置了其他所有内容。 then 回调保证异步调用。

你也可以使用setTimeout

sortColumn(): void {
    this.sortOrder = !this.sortOrder;
    setTimeout(() => {
        this.service.someExpensiveBlockingOperation();
        this.data.sort((a, b) => { ... });
    }, 0);
}

在符合 ES2015+ 的环境中,then 回调将比 setTimeout 回调更早地被调用,因为 promise 回调是“微任务”,在它们被调度的宏任务完成后立即运行,而 setTimeout回调是一个宏任务。在实践中,它很少相关(但,有时)。

【讨论】:

  • 谢谢! setTimeout() 正是我想要的。无论出于何种原因,Promise 仍然会延迟视图的更新。如果我能让它工作,我更喜欢使用 Promise。有任何想法吗?这是我现在拥有的:sort(): void { this.data.sort(...); setTimeout(() => expensiveOperation(), 0) }
  • @elli0t:啊,是的,视图的更新可能会在下一个宏任务中处理,所以这是微任务与宏任务的事情很重要的情况之一。如果您需要等待下一个宏任务,我认为您可以使用 Promise。
  • 你不会碰巧有任何关于微/宏任务的阅读材料吧?我从来没有听说过他们。
  • @elli0t:该术语有些非正式,源自HTML spec(讨论任务和微任务)。 JavaScript spec 谈到“工作”和“工作队列”(工作 = 任务),并清楚地将承诺解决工作与其他工作区分开来,但没有谈到在主要工作之间做这些工作。 (续)
  • (继续) 简短的版本是有一个主事件循环,任务(宏任务)被调度。任务期间排队的微任务在该任务完成后立即执行,队列中的下一个宏任务之前,即使宏任务首先排队。实施似乎正在就哪些工作是“宏观”与“微观”达成共识。 This question's answers 更多地谈论它。另请参阅我的回答 herehere。 HTH!
【解决方案2】:

如果你想要它异步,只需这样做

sortColumn(): void {
    this.service.someExpensiveBlockingOperation().subscribe(result => {
        // Do what you want here 
    });
    this.sortOrder = !this.sortOrder;
    this.data.sort((a, b) => { ... });
}

【讨论】:

  • 我想要相反的。我不希望它等待服务调用完成。服务调用应该开始,然后立即进入实际的排序操作。
  • 我已经尝试过类似的方法,但它并没有像我想要的那样工作。不过感谢您的回复。
猜你喜欢
  • 2019-01-10
  • 1970-01-01
  • 1970-01-01
  • 2019-10-09
  • 1970-01-01
  • 2019-05-01
  • 2023-03-05
  • 1970-01-01
  • 1970-01-01
相关资源
最近更新 更多