javascript – 为什么async / await打破$http.get /角度摘要周期?

看看下面的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(),那么变量将获得值“oranges”的更新并按预期显示在视图中.如果我们运行asyncTest(),视图将继续显示“apples”,直到某些内容强制摘要(出于某种原因,单击进出文本框似乎可以解决问题).

另一个奇怪的问题是,如果我们在asyncTest()中取消注释第二个await,那么该方法现在可以按预期工作.

为什么会发生这种情况,为什么第二个等待修复呢?我认为等待当时只是语法糖,所以这些应该是完全等价的.我找到了一些文章谈论这个问题,但他们更多的是关于如何解决它而不是在幕后发生的事情.

最佳答案 据我所知,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中.
但是当你添加注释掉的行等待$http.get(‘/ api / someApiCall’);在asyncTest函数中,将再次触发脏检查/摘要周期,从而更新UI.当您从像文本框这样的某个字段聚焦时,会发生同样的事情.

因为在测试函数内部你正在做这个.变量=“橙子”;在那里,一切正常.

点赞