我有一个叫做'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;
}]);
你的意见是极大的赞赏。
问候, 鲍勃
好吧,我想你是到这里的东西。我分配'那= this'构造'函数DashboardState(存储,ID,散列,widgetDefinitions,字符串化)'以上 - 和'that'现在包含有效的对象。 –
你是什么意思?它有用吗? – lex82
是的,它的工作。关键是在我的工厂代码的顶部添加'var that = this;';但是,外部我的构造函数。然后在'load:'函数内重新赋值'that = this;'。 –