2013-08-30 81 views
1

所以我們都知道'this'是JavaScript中一個棘手的關鍵字,匿名函數和AngularJS promise使它更加棘手。

問題(TL & DR版)

什麼是正確的(和角度)的方式,讓承諾回調 使用相同的「本」爲發起請求的服務?

看到這個搗鼓一個例子:

http://jsfiddle.net/tpeiffer/CFD3e/

所有的控制器上這些方法調用關閉的Tier1Service。 Tier1Service然後調用WorkerService來獲取數據。數據加載時,它通過對Tier1Service的承諾返回所述數據。返回的數據被設置到Tier1Service_data屬性中。

交替3是乾淨的,它的工作原理,但它感覺就像有一個更好的方法。

交替4也很乾淨,它的工作原理,但似乎又錯了。

現在我真正想要的是$ q的承諾爲我做這一切。 :)

下面是相關代碼:

// App.js 
    angular.constructor.prototype.call = function (scope, func) { 
     return function() { 
      func.apply(scope, arguments); 
     }; 
    }; 

// Tier1Service 
     get coolData() { 
      return this._data; 
     }, 
     set coolData(val) { 
      this._data = val; 
     }, 
     doWorkAlt1: function() { 
      mySubWorkerService.someData.then(function (data) { 
       // FAILS because 'this' is the window, 
       // not the service 
       if (data) this._data = data; 
      }); 
     }, 
     doWorkAlt2: function() { 
      mySubWorkerService.someData.then((function (data) { 
       // FAILS because data is undefined because 
       // the function is wrapped in an anonymous 
       // function 
       if (data) this._data = data; 
      }).call(this)); 
     }, 
     doWorkAlt3: function() { 
      // WORKS because I keep track of the instance 
      var instance = this; 
      mySubWorkerService.someData.then(function (data) { 
       if (data) instance._data = data; 
      }); 
     }, 
     doWorkAlt4: function() { 
      // WORKS because I keep pass 'this' around 
      mySubWorkerService.someData.then(angular.call(this, function (data) { 
       if (data) this._data = data; 
      })); 
     } 

// WorkerService 
     get someData() { 
      var deferred = $q.defer(); 
      deferred.resolve('i got back data!!'); 
      return deferred.promise; 
     } 
+0

你的問題是什麼? – zsong

+0

嗯,我認爲這篇文章措辭得很好,並且深思熟慮,但我想我已經很久了。我會更新這篇文章以更好地解釋它。 –

回答

1

你應該能夠使用Function.bind達到你想要的結果:

doWork: function() {   
    mySubWorkerService.someData.then((function(data) { 
     //this now refers to whatever it referred to in the doWork function 
    }).bind(this)); 
} 

做然而要注意bind是不是在舊的可用瀏覽器。但是,如果需要,可以很容易地將它打入原型。

+0

謝謝,@賈尼!那是缺失的環節!我不知道Function.bind。我們只將產品的重點放在採用非常新型瀏覽器的平板電腦上,因此ECMAScript 5功能完全可以接受!去展示這隻老狗仍然可以學習新的技巧! –