AngularJS、$http.get() 和 "controller as"

AngularJS, $http.get() and "controller as"

我对整个 AngularJS 世界及其工作方式还很陌生,但是我正在努力让它按预期工作。我知道这与我使用 $http.get() 并尝试将变量分配回我的控制器的方式有关,但我就是想不通。

使用 $scope 而不是 this 我可以让它工作,但是如果可能的话,我更愿意使用 this 这样我就可以使用 "controller as"

代码:

app.controller('ctrlSuppliers', function($http){

    this.supplierList = {};

    $http.get("http://some_url_here")
            .success(function(response) {  this.supplierList = response.records;})
            .error(function() { this.supplierList = [{supplier_id: 0, supplier_name: 'Error Getting  Details'}];});
});

从此示例中,我无法从 HTML 页面的 supplierList 中访问 $http.get 请求的任何结果(即 {{ supplier.supplierList[0].supplier_name }} 不显示任何结果)

我知道如果我将控制器更改为 $scope 我可以访问该数据(尽管使用的格式与上面不同),而且我也知道使用 console.log(this.supplierList).success 调用中。

我也知道它不起作用的原因是因为 this 的上下文从控制器内部更改为 $http.get 调用内部。

所以我的问题是:如何使用 this 而不是 scope 访问 $http.xxx 调用的结果?我已经阅读了一些关于它的不同来源,但大多数都在谈论使用 $scope 和承诺。我没有找到任何使用 this(或使用 var supplier = this 声明)的封面。任何帮助将不胜感激。

谢谢,

始终存储对 this 的变量引用,这样您就不会遇到上下文问题,然后在整个控制器

中使用该变量而不是 this
app.controller('ctrlSuppliers', function($http){
    var vm = this;
    // now can forget using "this" and use variable instead
    vm.supplierList = {};

    $http.get("http://some_url_here") .success(function(response) {
         // no context issues since "vm" is in scope  
         vm.supplierList = response.records;
    });               
});

对于 $http,您可以选择将自己的对象存储在 configObject 中,这是 $http.get() 的可选第二个参数。然后您可以使用此对象,因为它是 response 的 属性。

如果您在一个循环中多次调用 $http.get(),此技术特别有用。

我认为 charlietfl 的回答是正确的,但认为稍微扩展一下的解释可能会有所帮助。

"this" in javascript 引用当前函数调用的上下文。如果你查看你的代码,你会发现它被用在两个函数中 -

app.controller('ctrlSuppliers', function($http){

    //first use of this - used in the context of the controller function
    //In this case, this = the controller
    this.supplierList = {};

    $http.get("http://some_url_here")
            .success(function(response) {  
                //second use of this - used in the context of the http success function callback
                //this will likely not be the controller.  It's value depends on how the caller (the $http framework) invoked the method.
                this.supplierList = response.records;
             })
             ....

由于它们是两个不同的函数,它们可能具有完全不同的上下文,因此"this"将指代不同的对象(如您所经历的)。

处理这个问题的标准方法是保存第一个函数的调用上下文以供其他函数使用。 @charlietfl 的回答是完成此任务的好方法。我已经添加了他的代码以供参考。

app.controller('ctrlSuppliers', function($http){
    var vm = this;
    vm.supplierList = {};

    $http.get("http://some_url_here")
            .success(function(response) {  vm.supplierList = response.records;})
});

this 变量在 JavaScript 中很棘手。执行回调函数时,您不会知道 this 引用的是什么。除非它被记录在某处。

您必须使用 .bind(this) 附加您自己的 this 值以在函数中使用。

app.controller('ctrlSuppliers', function($http){
    this.supplierList = {};
    $http.get("http://some_url_here")
            .success(function(response) {
                 this.supplierList = response.records;
            }.bind(this))
            .error(function() { 
                 this.supplierList = [{supplier_id: 0, supplier_name: 'Error Getting  Details'}];
            }.bind(this));
});

参见绑定手册:

https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Function/bind

有了 ecmascript 6 中可用的箭头函数,this 的问题得到了解决,您可以输入更少的内容。您的示例如下所示:

app.controller('ctrlSuppliers', function($http){
    this.supplierList = {};

    $http.get("http://some_url_here")
            .success(response => { this.supplierList = response.records; })
            .error(() => { this.supplierList = [{supplier_id: 0, supplier_name: 'Error Getting  Details'}]; });
});

结果相当于将this存储到变量中,但更简洁。