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

7

我对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,我就可以访问那些数据(虽然不使用上述相同的格式),我也知道数据是通过在.success调用内使用console.log(this.supplierList)进行填充的。
我也知道它不起作用的原因是因为this的上下文从控制器内部变为了$http.get调用内部。
所以我的问题是:如何使用this而不是scope访问来自$http.xxx调用的结果?我已经阅读了一些不同的来源,但大多数都谈到了使用$scope和promises。我没有找到任何涵盖使用this(或使用var supplier = this声明它)的方法。非常感谢您的帮助。
谢谢,

提醒一下,$http调用通常不应该放在控制器中!将它们提取到服务中以实现可重用性、稳定性和非必要的依赖注入。 - Hypaethral
@GrumbleSnatch 谢谢你。正如我所说,我刚开始学习Angular,还没有时间浏览所有的功能和函数,但现在知道它们很可能会在我最终发现它们时为我节省很多时间。 - Doug
5个回答

9

始终存储一个变量引用到 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;
    });               
});

1
我确定昨晚我尝试过那种方法,但它对我没有起作用。然而,将 this 声明为一个变量并引用该变量现在可以工作了。如此简单 - 非常感谢。 - Doug
1
对于任何正在阅读此内容的人来说,success 已经被弃用了。请使用 .then 代替。 - Miguel Xoel Garcia

2
对于 $http,你有存储自己对象的选项,这个对象是可选的第二个参数 configObject,可以在调用 $http.get() 方法时传入。这个对象随后作为 response 的一个属性供你使用。
如果你在循环中多次调用 $http.get(),那么这种技术尤其有用。

2

使用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存储到一个变量中,但更加简洁。


2

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));
});

请参考bind手册: https://developer.mozilla.org/zh-CN/docs/Web/JavaScript/Reference/Global_Objects/Function/bind

1
我认为charlietfl的答案是正确的,但我认为稍微扩展一下解释可能会更有帮助。
在javascript中,“this”指当前函数调用的上下文。如果您查看代码,您会发现“this”在两个函数中被使用 -
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;})
});

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接