class 定义中的闭包问题
Closure problems in class definition
我正在使用 CoffeScript 创建一个 angular 应用程序。
这段代码有一个奇怪的问题。
webService.coffe(简体)
ServiceManager.service "webService", class
constructor : (@$http) ->
# Private
handleResult = (callback, errorCallback, authErrorCallback) =>
(result) =>
if result.result then callback result
else
if result.code is 102 then @logout authErrorCallback, errorCallback
else errorCallback result.code, result.error
get : (url, callback, errorCallback) ->
@$http.get url
.success handleResult callback, errorCallback, (=> @get url, callback, errorCallback)
.error handleError errorCallback
logout : (callback, errorCallback) ->
@$http.get "logout"
.success callback()
.error errorCallback()
在这个简化的代码中,调用 handleResult
时出现错误 _Class.logout is not a function
,错误代码为 102。
=>
运算符应该可以解决这个问题,但事实并非如此。我不明白为什么...
Javascript webService.coffee
的编译代码
ServiceManager.service("webService", (function() {
var handleResult;
function _Class($http) {
this.$http = $http;
}
handleResult = function(callback, errorCallback, authErrorCallback) {
return function(result) {
if (result.result) {
return callback(result);
} else {
if (result.code === 102) {
return _Class.logout(authErrorCallback, errorCallback);
} else {
return errorCallback(result.code, result.error);
}
}
};
};
_Class.prototype.get = function(url, callback, errorCallback) {
return this.$http.get(url).success(handleResult(callback, errorCallback, ((function(_this) {
return function() {
return _this.get(url, callback, errorCallback);
};
})(this)))).error(handleError(errorCallback));
};
_Class.prototype.logout = function(callback, errorCallback) {
return this.$http.get("logout").success(callback()).error(errorCallback());
};
return _Class;
})());
您的问题是您将 handleResult
定义为 class IIFE 中的静态私有变量。它无法访问 @logout
实例方法,因此,CS 确实将其编译为静态 _Class.logout
调用,该调用无法工作。
有几种解决方法:
- 将
handleResult
设为私有实例变量,并将所有内容移动到构造函数中 - @get
和 @logout
的声明也是如此。
- 给
handleResult
一个你传递给@
的实例参数,这样它就可以调用它的实例方法
- 只调用
authErrorCallback
并执行 @logout
和里面的事情。
鉴于您的服务 class 无论如何只会作为单例实例化一次,第一个可能是最明智的。
但是,无论如何,您真的应该考虑不要做那么复杂的回调。只需使用承诺:
ServiceManager.service "webService", class
constructor : (@$http) ->
get: (url) ->
@$http.get url
.then (result) =>
if result.result then result
else if result.code is 102 then @logout().then(=> @get url)
else throw result.error
logout: () ->
@$http.get "logout"
我正在使用 CoffeScript 创建一个 angular 应用程序。
这段代码有一个奇怪的问题。
webService.coffe(简体)
ServiceManager.service "webService", class
constructor : (@$http) ->
# Private
handleResult = (callback, errorCallback, authErrorCallback) =>
(result) =>
if result.result then callback result
else
if result.code is 102 then @logout authErrorCallback, errorCallback
else errorCallback result.code, result.error
get : (url, callback, errorCallback) ->
@$http.get url
.success handleResult callback, errorCallback, (=> @get url, callback, errorCallback)
.error handleError errorCallback
logout : (callback, errorCallback) ->
@$http.get "logout"
.success callback()
.error errorCallback()
在这个简化的代码中,调用 handleResult
时出现错误 _Class.logout is not a function
,错误代码为 102。
=>
运算符应该可以解决这个问题,但事实并非如此。我不明白为什么...
Javascript webService.coffee
的编译代码ServiceManager.service("webService", (function() {
var handleResult;
function _Class($http) {
this.$http = $http;
}
handleResult = function(callback, errorCallback, authErrorCallback) {
return function(result) {
if (result.result) {
return callback(result);
} else {
if (result.code === 102) {
return _Class.logout(authErrorCallback, errorCallback);
} else {
return errorCallback(result.code, result.error);
}
}
};
};
_Class.prototype.get = function(url, callback, errorCallback) {
return this.$http.get(url).success(handleResult(callback, errorCallback, ((function(_this) {
return function() {
return _this.get(url, callback, errorCallback);
};
})(this)))).error(handleError(errorCallback));
};
_Class.prototype.logout = function(callback, errorCallback) {
return this.$http.get("logout").success(callback()).error(errorCallback());
};
return _Class;
})());
您的问题是您将 handleResult
定义为 class IIFE 中的静态私有变量。它无法访问 @logout
实例方法,因此,CS 确实将其编译为静态 _Class.logout
调用,该调用无法工作。
有几种解决方法:
- 将
handleResult
设为私有实例变量,并将所有内容移动到构造函数中 -@get
和@logout
的声明也是如此。 - 给
handleResult
一个你传递给@
的实例参数,这样它就可以调用它的实例方法 - 只调用
authErrorCallback
并执行@logout
和里面的事情。
鉴于您的服务 class 无论如何只会作为单例实例化一次,第一个可能是最明智的。
但是,无论如何,您真的应该考虑不要做那么复杂的回调。只需使用承诺:
ServiceManager.service "webService", class
constructor : (@$http) ->
get: (url) ->
@$http.get url
.then (result) =>
if result.result then result
else if result.code is 102 then @logout().then(=> @get url)
else throw result.error
logout: () ->
@$http.get "logout"