我的 Angular 工厂代码中的范围问题 [英] Scope issues in my Angular factory code

查看:21
本文介绍了我的 Angular 工厂代码中的范围问题的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

我有一个名为 'DashboardState' 的 Angular 工厂,我目前正在修改它以通过我的 dashboardcontext Angular 服务层处理 API 调用.

I have an Angular factory called 'DashboardState', which I am currently modifying to handle an API call via my dashboardcontext Angular service layer.

目前我所有的 widget 数据都被持久化到 localStorage 对象;但是,我现在正在连接到一个新的 c# API 层,该层将布局小部件设置为/从永久存储(即在这种情况下为 Sql Server 数据库).

Currently all my widget data is persisted to the localStorage object; however, I am now hooking into a new c# API layer which sets/gets the layout widgets to/from permanent storage (i.e. Sql Server database in this case).

我的主要问题是当 promisereturn this._getItemFromAPI($rootScope).thenload: 处返回时会发生什么功能.

My primary issue is what happens when the promise is returned at return this._getItemFromAPI($rootScope).then of the load: function.

load:部分,this是一个有效的对象,在栈上有方法;但是,在 .then 部分中,我突然无法访问 this..

In the load: section, this is a valid object with methods on the stack; however, within the .then section I suddenly lose access to this..

这对我来说是个问题,因为我无法再调用 this._handleSyncLoad.正如您所看到的,我已经尝试通过分配 var handleSync = this._handleSyncLoad; 来进行破解,但是它并没有解决范围问题.:

It's a problem for me because I can no longer call this._handleSyncLoad. And as you can see, I've tried a hack by assigning var handleSync = this._handleSyncLoad;, however it doesn't solve the scope issue.:

  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' 的完整列表:

Here's the full listing of '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                  
	      // COME CODE OMITTED FOR BREVITY
	      serialized = this.storage.getItem(dashboardId);                  
	  }
      }
      else {                  

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

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

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

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

      if (serialized) {
	  // check for promise
	  if (angular.isObject(serialized)) {    // && angular.isFunction(serialized.then)) {    // modifed line 09/04/2015 BM:
	      return this._handleAsyncLoad(serialized);
	  }
	  // otherwise handle synchronous load
	  return this._handleSyncLoad(serialized);
      } else {
	  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) {
	  if (data.status == "FAIL") {
	      window.alert("Failed to retrieve dashboard. " + data.messages);
	      return false;
	  }
	  else {                      
	      return data;
	  }
      });            
  },

  _handleSyncLoad: function (serialized, isParsed) {


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

      var deserialized, result = [];

      if (!serialized) {
	  return null;
      }

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

	  deserialized = JSON.parse(serialized);

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

		  deserialized = JSON.parse(serialized);

	      } catch (e) {

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

	      }
	  }
	  else {
	      deserialized = serialized;
	  }
      }

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

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

      }

      // Cache widgets
      var savedWidgetDefs = deserialized.widgets;

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

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

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

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

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

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

      return result;
  },

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

      return deferred.promise;
  }

};

return DashboardState;
}]);

非常感谢您的建议.

问候,鲍勃

推荐答案

this 总是引用当前函数,所以如果你嵌套函数定义,你必须以某种方式解决它.

this always refers to the current function so if you nest function definitions you have to work around it somehow.

这是应该可以解决您的问题的典型模式:

This is a typical pattern that should solve your issue:

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

这篇关于我的 Angular 工厂代码中的范围问题的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆