看看下面的Angular 1.x控制器:
class RootController
{
constructor($http)
{
this.variable = "apples";
// this.test($http); -- this works
// this.asyncTest($http); -- this doesn't
}
async asyncTest($http)
{
await $http.get('/api/someApiCall');
this.variable = "oranges";
// await $http.get('/api/someApiCall'); -- this makes this method work
}
test($http)
{
$http.get('/api/someApiCall').then(() => {
this.variable = "oranges";
});
}
}
如果我们取消注释构造函数中两个注释掉的行之一,我们会得到不同的行为。如果我们运行test()
,那么variable
会获得值“oranges”的更新并按预期显示在视图中。如果我们运行asyncTest()
,视图将继续显示“apples”,直到某些内容强制摘要(出于某种原因,单击进出文本框似乎可以解决问题)。
另一个奇怪的问题是,如果我们在await
中取消注释第二个asyncTest()
,那么该方法现在可以按预期工作。
为什么会发生这种情况,为什么第二个await
会修复它?我认为await
几乎只是then
的语法糖,所以这些应该完全相同。我找到了一些文章谈论这个问题,但他们更多的是关于如何解决它而不是在幕后发生的事情。
据我所知,Javascript中的Async Await功能是使用Promises和Generators的巧妙组合实现的,这对我来说太聪明了,无法详细解释。但如果你有兴趣,你可以看看这些:https://chromium.googlesource.com/v8/v8.git/+/d08c0304c5779223d6c468373af4815ec3ccdb84/src/js/harmony-async-await.js#34
https://curiosity-driven.org/promises-and-generators
async/await native implementations
因此,由于Promise已经解决并且Angular脏检查/摘要周期将在生成器生成之前完成,因此this.variable = "oranges";
函数内的asyncTest
将不会反映在UI中。但是当你在await $http.get('/api/someApiCall');
函数中添加注释掉的行asyncTest
时,将再次触发脏检查/摘要周期,从而更新UI。当您从像文本框这样的某个字段聚焦时,会发生同样的事情。
因为在test
函数里面你在this.variable = "oranges";
里面做then
,一切正常。