奇怪的 Javascript 关闭错误
Weird Javascript closure bug
这是一些代码。
function callServiceSync(url, obj) {
var result = true;
callServiceOptions(url, obj, function(res){
result = res;
alert("RESULT CB: "+JSON.stringify(result));
}, {async: false});
alert("RESULT POST-CB: "+JSON.stringify(result));
return result;
}
运行时,警告框显示:
RESULT CB: {"success":true,"data":"dtrombley"}
(这就是网络服务 returns,实际上),然后:
RESULT POST-CB: true
为什么对闭包变量的赋值不起作用?我是不是误解了 JS 闭包的工作原理?
callServiceOptions() 相当冗长 - 但它的要点是它调用 jQuery 的 $.ajax 方法,它的最后一个参数选项扩展到一些默认值(在这种情况下, async 为同步查询禁用),然后执行提供的回调。
Is $.ajax() 可能以某种方式执行某事 disables/screws 闭包(但 I 调用 cb,而不是 $ .ajax()!)?如果是,如何解决?
为了完整起见(尽管按照我的想法,这个函数真的不应该搞砸):
function callServiceOptions(url, obj, cb, options) {
optSuccess = options.success;
optError = options.error;
opts = {}
$.extend({},options)
if (!opts.contentType) {
opts.contentType = "application/json";
}
if (!opts.dataType) {
opts.dataType = "json";
}
if (!opts.data && obj) {
opts.data = JSON.stringify(obj);
}
if (!opts.processData) {
opts.processData = false;
}
if (!opts.method) {
opts.method = "POST";
}
opts.error = function(jqXHR, textStatus, errorThrown) {
if (optError) {
optError(jqXHR, textStatus, errorThrown);
}
if (jqXHR.responseText) {
responseObj = JSON.parse(jqXHR.responseText)
if (responseObj && responseObj.message)
cb({
success: false,
message: responseObj.message
})
return
}
cb({
success: false,
message: errorThrown
});
};
opts.success = function(data, textStatus, jqXHR) {
if (optSuccess) {
optSuccess(data,textStatus,jqXHR);
}
cb(data);
};
if (url.charAt(0) == '/') {
url = url.substr(1);
}
opts.url = WEBCTX.getBaseURL() + url;
$.ajax(opts);
}
这不是询问如何 return 来自异步事件的值的任何问题的副本。我有一个工作的 callServiceAsync() ,它做得很漂亮。我使用的是同步模式,如果你不熟悉,请绕过这个问题...
你的函数是异步的。
虽然您创建了一个看起来像 {async: false}
的对象,但您将它作为第 4 个参数传递给 callServiceOptions
,因此它被放置在 options
变量中。
您只访问该变量两次(options.success
和 options.error
),因此 async
属性 永远不会用于任何事情(因此 $.ajax
使用默认值 true
).
在您调用 $.ajax(opts);
之前添加 console.log(opts)
将显示此内容。
这是一些代码。
function callServiceSync(url, obj) {
var result = true;
callServiceOptions(url, obj, function(res){
result = res;
alert("RESULT CB: "+JSON.stringify(result));
}, {async: false});
alert("RESULT POST-CB: "+JSON.stringify(result));
return result;
}
运行时,警告框显示:
RESULT CB: {"success":true,"data":"dtrombley"}
(这就是网络服务 returns,实际上),然后:
RESULT POST-CB: true
为什么对闭包变量的赋值不起作用?我是不是误解了 JS 闭包的工作原理?
callServiceOptions() 相当冗长 - 但它的要点是它调用 jQuery 的 $.ajax 方法,它的最后一个参数选项扩展到一些默认值(在这种情况下, async 为同步查询禁用),然后执行提供的回调。
Is $.ajax() 可能以某种方式执行某事 disables/screws 闭包(但 I 调用 cb,而不是 $ .ajax()!)?如果是,如何解决?
为了完整起见(尽管按照我的想法,这个函数真的不应该搞砸):
function callServiceOptions(url, obj, cb, options) {
optSuccess = options.success;
optError = options.error;
opts = {}
$.extend({},options)
if (!opts.contentType) {
opts.contentType = "application/json";
}
if (!opts.dataType) {
opts.dataType = "json";
}
if (!opts.data && obj) {
opts.data = JSON.stringify(obj);
}
if (!opts.processData) {
opts.processData = false;
}
if (!opts.method) {
opts.method = "POST";
}
opts.error = function(jqXHR, textStatus, errorThrown) {
if (optError) {
optError(jqXHR, textStatus, errorThrown);
}
if (jqXHR.responseText) {
responseObj = JSON.parse(jqXHR.responseText)
if (responseObj && responseObj.message)
cb({
success: false,
message: responseObj.message
})
return
}
cb({
success: false,
message: errorThrown
});
};
opts.success = function(data, textStatus, jqXHR) {
if (optSuccess) {
optSuccess(data,textStatus,jqXHR);
}
cb(data);
};
if (url.charAt(0) == '/') {
url = url.substr(1);
}
opts.url = WEBCTX.getBaseURL() + url;
$.ajax(opts);
}
这不是询问如何 return 来自异步事件的值的任何问题的副本。我有一个工作的 callServiceAsync() ,它做得很漂亮。我使用的是同步模式,如果你不熟悉,请绕过这个问题...
你的函数是异步的。
虽然您创建了一个看起来像 {async: false}
的对象,但您将它作为第 4 个参数传递给 callServiceOptions
,因此它被放置在 options
变量中。
您只访问该变量两次(options.success
和 options.error
),因此 async
属性 永远不会用于任何事情(因此 $.ajax
使用默认值 true
).
在您调用 $.ajax(opts);
之前添加 console.log(opts)
将显示此内容。