2015-09-08 17 views
2

我有一个叫做'DashboardState'的Angular工厂,我目前正在修改它以通过我的dashboardcontext Angular服务层处理API调用。我的Angular工厂代码中的范围问题

目前我所有的widget数据仍保持为localStorage对象;不过,我现在挂接到这台新的C#API层/获取布局小部件/从永久存储(即SQL Server数据库在这种情况下)。

我的主要问题是promise返回load:函数的return this._getItemFromAPI($rootScope).then时会发生什么。

load:部分,this是一个有效的对象,其方法在堆栈上;然而,.then部分中我突然失去this.访问。

这是我的问题,因为我不能再调用this._handleSyncLoad。正如你所看到的,我已经通过分配var handleSync = this._handleSyncLoad;尝试黑客攻击,但它并没有解决问题的范围:

if (dashboardId != null && dashboardId != undefined) { 

        this.storage.setItem("defaultDashboardId", dashboardId); 

        var handleSync = this._handleSyncLoad; 
        return this._getItemFromAPI($rootScope).then(function (data) {       
         // save current current dashboard id for next time - 06/11/2015 BM:  

         return handleSync(data, true);  

        });      
       } 

这里是'DashboardState'完整清单:

angular.module('ui.dashboard') 
 
.factory('DashboardState', ['$log', '$q', 'dashboardcontext', '$rootScope', function ($log, $q, dashboardcontext, $rootScope) { 
 
function DashboardState(storage, id, hash, widgetDefinitions, stringify) { 
 
    this.storage = storage; 
 
    this.id = id; 
 
    this.hash = hash; 
 
    this.widgetDefinitions = widgetDefinitions; 
 
    this.stringify = stringify; 
 
} 
 

 
DashboardState.prototype = { 
 
    /** 
 
    * Takes array of widget instance objects, serializes, and saves state. 
 
    * 
 
    * @param {Array} widgets scope.widgets from dashboard directive 
 
    * @return {Boolean}  true on success, false on failure 
 
    */ 
 
save: function (widgets) {    
 
     // CODE OMITTED FOR SAVE FUNCTION 
 
     return true; 
 
    },     
 
load: function (dashboardId) {  // sent in from navigation-controller call 
 

 
     var useLocalStorage = false;  // retrieve from localStorage or via API layer 
 

 
     var serialized; 
 

 
     if (useLocalStorage) {   // retrieve dashboard layout from localStorage     
 
\t  // COME CODE OMITTED FOR BREVITY 
 
\t  serialized = this.storage.getItem(dashboardId);     
 
\t } 
 
     } 
 
     else {     
 

 
\t // FETCH DASHBOARD HERE !! 
 
\t if (dashboardId != null && dashboardId != undefined) { 
 

 
\t  // *** "this" is available on the scope at this point *** 
 
\t  this.storage.setItem("defaultDashboardId", dashboardId); 
 

 
\t  var handleSync = this._handleSyncLoad; 
 
\t  return this._getItemFromAPI($rootScope).then(function (data) {               
 
\t \t // *** "this" IS NO LONGER AVAILABLE ON THE SCOPE - i.e. I can no longer call this._handleSyncLoad from here *** 
 
\t \t return handleSync(data, true);  
 

 
\t  });      
 
\t } 
 
\t else { 
 
\t  // revert to original line; see dashboardOptions to main-controller 
 
\t  serialized = this.storage.getItem(this.id); 
 
\t }     
 
     } 
 

 
     if (serialized) { 
 
\t // check for promise 
 
\t if (angular.isObject(serialized)) { // && angular.isFunction(serialized.then)) { // modifed line 09/04/2015 BM: 
 
\t  return this._handleAsyncLoad(serialized); 
 
\t } 
 
\t // otherwise handle synchronous load 
 
\t return this._handleSyncLoad(serialized); 
 
     } else { 
 
\t return null; 
 
     } 
 

 
    },   
 

 
    _getItemFromAPI: function ($rootscope) { 
 
     // SERVER-SIDE API CALL TO PERSIST DASHBOARD TO STORAGE - 09/03/2015 BM: 
 
     var sid = $rootScope.rageSessionVars.sessionID; 
 
     var userid = $rootScope.rageSessionVars.userID; 
 
     var dashboardId = this.id; 
 

 
     return dashboardcontext.getDashboardImage(sid, userid, dashboardId).then(function (data) { 
 
\t if (data.status == "FAIL") { 
 
\t  window.alert("Failed to retrieve dashboard. " + data.messages); 
 
\t  return false; 
 
\t } 
 
\t else {      
 
\t  return data; 
 
\t } 
 
     });    
 
    }, 
 

 
    _handleSyncLoad: function (serialized, isParsed) { 
 

 

 
     // **** MUST HANDLE THE isParsed PARAM; serialized object is alredy parsed **** 
 

 
     var deserialized, result = []; 
 

 
     if (!serialized) { 
 
\t return null; 
 
     } 
 

 
     if (this == undefined) { // problem if coming from .then of this._getItemFromAPI in load: - 09/04/2015 BM: 
 

 
\t deserialized = JSON.parse(serialized); 
 

 
     } 
 
     else { 
 
\t if (this.stringify) { 
 
\t  try { // to deserialize the string 
 

 
\t \t deserialized = JSON.parse(serialized); 
 

 
\t  } catch (e) { 
 

 
\t \t // bad JSON, log a warning and return 
 
\t \t $log.warn('Serialized dashboard state was malformed and could not be parsed: ', serialized); 
 
\t \t return null; 
 

 
\t  } 
 
\t } 
 
\t else { 
 
\t  deserialized = serialized; 
 
\t } 
 
     } 
 

 
     // check hash against current hash 
 
     if (deserialized.hash !== this.hash) { 
 

 
\t $log.info('Serialized dashboard from storage was stale (old hash: ' + deserialized.hash + ', new hash: ' + this.hash + ')'); 
 
\t this.storage.removeItem(this.id); 
 
\t return null; 
 

 
     } 
 

 
     // Cache widgets 
 
     var savedWidgetDefs = deserialized.widgets; 
 

 
     // instantiate widgets from stored data 
 
     for (var i = 0; i < savedWidgetDefs.length; i++) { 
 

 
\t // deserialized object 
 
\t var savedWidgetDef = savedWidgetDefs[i]; 
 

 
\t // widget definition to use 
 
\t var widgetDefinition = this.widgetDefinitions.getByName(savedWidgetDef.name); 
 

 
\t // check for no widget 
 
\t if (!widgetDefinition) { 
 
\t  // no widget definition found, remove and return false 
 
\t  $log.warn('Widget with name "' + savedWidgetDef.name + '" was not found in given widget definition objects'); 
 
\t  continue; 
 
\t } 
 

 
\t // check widget-specific storageHash 
 
\t if (widgetDefinition.hasOwnProperty('storageHash') && widgetDefinition.storageHash !== savedWidgetDef.storageHash) { 
 
\t  // widget definition was found, but storageHash was stale, removing storage 
 
\t  $log.info('Widget Definition Object with name "' + savedWidgetDef.name + '" was found ' + 
 
\t \t 'but the storageHash property on the widget definition is different from that on the ' + 
 
\t \t 'serialized widget loaded from storage. hash from storage: "' + savedWidgetDef.storageHash + '"' + 
 
\t \t ', hash from WDO: "' + widgetDefinition.storageHash + '"'); 
 
\t  continue; 
 
\t } 
 

 
\t // push instantiated widget to result array 
 
\t result.push(savedWidgetDef); 
 
     } 
 

 
     return result; 
 
    }, 
 

 
    _handleAsyncLoad: function (promise) { 
 
     var self = this; 
 
     var deferred = $q.defer(); 
 
     promise.then(
 
\t // success 
 
\t function (res) { 
 
\t  var result = self._handleSyncLoad(res); 
 
\t  if (result) { 
 
\t \t deferred.resolve(result); 
 
\t  } else { 
 
\t \t deferred.reject(result); 
 
\t  } 
 
\t }, 
 
\t // failure 
 
\t function (res) { 
 
\t  deferred.reject(res); 
 
\t } 
 
    ); 
 

 
     return deferred.promise; 
 
    } 
 

 
}; 
 

 
return DashboardState; 
 
}]);

你的意见是极大的赞赏。

问候, 鲍勃

回答

1

this总是指当前的函数,所以如果你你有嵌套函数定义来解决它在某种程度上。

这是一个应该解决您的问题的典型模式:

function someFunction() { 
    var that = this; 
    doSomething().then(function() { 
    // 'that' is your 'this' 
    }); 
} 
+0

好吧,我想你是到这里的东西。我分配'那= this'构造'函数DashboardState(存储,ID,散列,widgetDefinitions,字符串化)'以上 - 和'that'现在包含有效的对象。 –

+0

你是什么意思?它有用吗? – lex82

+0

是的,它的工作。关键是在我的工厂代码的顶部添加'var that = this;';但是,外部我的构造函数。然后在'load:'函数内重新赋值'that = this;'。 –