如何在链式$ request promises中访问$ scope?

时间:2014-01-31 12:51:38

标签: angularjs promise angularjs-resource

我有一个看起来像这样的承诺链......

this.getFile(fileId).then(updateFile).then(displayAllDoneMessage);

其中getFile()updateFile()各使用ngResource来构建相应的JSON调用,然后返回$resource.$promise

链条触发正常,但我在$scope

内访问updateFile时遇到问题

所以getFile()我有

// this works
this.status.text = "fetching file"

但在updateFile()我有

// this fails at runtime because "this" is not $scope
this.status.text = "updating file"

我做错了什么,或者我需要做些什么才能在$scope内提供updateFile()

我应该补充说,我正在使用TypeScript,以防万一。

2 个答案:

答案 0 :(得分:3)

如果您正在使用TypeScript并且想要维护this指针,那么您需要确保使用lambda语法。

假设您已将$scope作为私有/公共变量保存在构造函数中,如下所示:

constructor(private $scope){ /* snip */ }

然后您可以这样做,以确保您正在访问$scope,如此:

this.getFile(fileid)
.then((result) => {
   return this.$scope.updateFile(result);
})
.then((result) => {
   return this.$scope.displayAllDoneMessage(result);
});

在引擎盖下,这会被编译成如下所示:

//Save 'this' off to a closure
var _this = this;

_this.getFile(fileid)
.then(function(result){
   return _this.$scope.updateFile(result);
})
.then(function(result){
   return _this.$scope.displayAllDoneMessage(result);
});

TypeScipt使用闭包来维护对this

的适当引用

答案 1 :(得分:0)

当您致电this.getFile时,上下文为this,在您的情况下,我猜this是$ scope对象,因此this内的getFile是$ scope。

但框架会调用updateFiledisplayAllDoneMessage作为回调,this不再引用$ scope。

尝试.bind将$ scope绑定为上下文:

this.getFile(fileId).then(updateFile.bind(this)).then(displayAllDoneMessage.bind(this));

对于旧版浏览器,您可以将此脚本包含为polyfill(引自文档):

if (!Function.prototype.bind) {
  Function.prototype.bind = function (oThis) {
    if (typeof this !== "function") {
      // closest thing possible to the ECMAScript 5 internal IsCallable function
      throw new TypeError("Function.prototype.bind - what is trying to be bound is not callable");
    }

    var aArgs = Array.prototype.slice.call(arguments, 1), 
        fToBind = this, 
        fNOP = function () {},
        fBound = function () {
          return fToBind.apply(this instanceof fNOP && oThis
                                 ? this
                                 : oThis,
                               aArgs.concat(Array.prototype.slice.call(arguments)));
        };

    fNOP.prototype = this.prototype;
    fBound.prototype = new fNOP();

    return fBound;
  };
}