为什么$scope.someArray.Push not一个有效的函数传递给$q.promise上的.then



相关内容:https://jsfiddle.net/tqf4zea7/1/

我在angular控制器中使用$q。为了测试一些场景,我在作用域上创建了一个数组,将消息推送到:

$scope.messages = [];

我设置了一个返回$q函数的函数,如下所示:

function returnAPromise(valToReturn){
    return $q(function(resolve, reject){
        $timeout(function(){
            resolve(valToReturn);
        }, 500);
    });
}

然后我有一个.then()调用的结果看起来像这样:

returnAPromise('third').then($scope.messages.push);

由于我只想将承诺解析的值推入数组,因此我认为我可以传入消息数组的push方法,但是当我这样做时,我得到以下错误:

VM289 angular.js:12520 TypeError: Array.prototype.push called on null or undefined
    at processQueue (VM289 angular.js:14792)
    at VM289 angular.js:14808
    at Scope.$eval (VM289 angular.js:16052)
    at Scope.$digest (VM289 angular.js:15870)
    at Scope.$apply (VM289 angular.js:16160)
    at VM289 angular.js:17927
    at completeOutstandingRequest (VM289 angular.js:5552)
    at VM289 angular.js:5829

如果我在一个函数中包含push,它工作得很好:

returnAPromise('third').then(function(message){ 
     $scope.messages.push(message) 
});

这是我不理解的闭包问题吗?

你需要绑定push,因为它使用this

returnAPromise('third').then($scope.messages.push.bind($scope.messages));

我知道有一个公认的答案,但我将在这里解释得更清楚

<标题> 例子

让我们从一个例子

开始
var scope = {
  scopeFn: function() {
    console.log('this', this)
  }
}
function callFn(fn) {
  fn();
}
callFn(obj.scopeFn) // will log window object 
callFn(function() {
  obj.scopeFn();
});// will log scope object

正如你所看到的,包装函数将给被调用的对象this的值,但是直接调用它而不包装它将调用window对象。

<标题>为什么?

this将绑定到它调用的对象。

在第一个示例callFn(obj.scopeFn)中,您将函数作为参数传递,因此当函数被调用时,它直接被调用,而不是从scope对象。(scope对象丢失,只发送函数引用)。

在第二个示例中,

从对象调用函数scopeFn,因此this将绑定到它的对象。(scope对象不会丢失,因为当它被调用时整个东西都在那里)

<标题> 解决方案

要解决这个问题,你需要绑定你传递的函数作为解析的参数,这样它将总是被调用,就像它是从它的父对象调用一样。

var scopeMessage = $scope.messages;
returnAPromise('third').then(scopeMessage.push.bind(scopeMessage));

最新更新