奇怪的Javascript闭包错误
下面是一些代码奇怪的Javascript闭包错误,javascript,jquery,ajax,synchronous,Javascript,Jquery,Ajax,Synchronous,下面是一些代码 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.s
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;
}
运行时,警报框显示:
结果CB:{“success”:true,“data”:“dtrombley”}
(事实上,这就是Web服务返回的结果),然后:
CB后的结果:正确
为什么对闭包变量的赋值不起作用?我是否误解了JS闭包的工作原理
callServiceOptions()相当冗长,但其要点是,它调用jQuery的$.ajax方法,并将其最后的参数选项扩展为某种默认值(在本例中,sync query禁用async),然后执行提供的回调
$.ajax()是否以某种方式执行某些操作,从而禁用/破坏闭包(但是I调用cb,而不是$.ajax()!)?如果是,如何解决
为了完整性(尽管这个函数实际上不应该把事情搞砸):
这不是询问如何从异步事件返回值的问题的重复。我有一个正在工作的callServiceAsync(),它做得很好。我使用的是同步模式,如果您不熟悉,请跳过这个问题…您的函数是异步的 当您创建了一个看起来像
{async:false}
的对象时,您将它作为第四个参数传递给callServiceOptions
,因此它将被放置在options
变量中
您只访问该变量两次(options.success
和options.error
),因此async
属性从不用于任何事情(因此$。ajax
使用默认值true
)
在调用
$.ajax(opts)之前添加console.log(opts)
代码>将显示这一点。您的函数是异步的
当您创建了一个看起来像{async:false}
的对象时,您将它作为第四个参数传递给callServiceOptions
,因此它将被放置在options
变量中
您只访问该变量两次(options.success
和options.error
),因此async
属性从不用于任何事情(因此$。ajax
使用默认值true
)
在调用$.ajax(opts)之前添加console.log(opts)
代码>将显示这一点。昆廷-请仔细阅读问题。我不是在执行异步调用,而是在执行同步调用,值是从jQuery ajax()正确返回的。不,我使用的是同步查询模式。请阅读位于的文档,特别是关于我正在使用的“async”选项的部分。如果是async,则警报不会按该顺序返回,但会以相反的顺序返回。我在您的代码中没有看到任何说明使用同步请求的内容……您的注释现在看起来有点像(在此处填入合适的词)。-)昆廷-请仔细阅读问题。我不是在执行异步调用,而是在执行同步调用,值是从jQuery ajax()正确返回的。不,我使用的是同步查询模式。请阅读位于的文档,特别是关于我正在使用的“async”选项的部分。如果是async,则警报不会按该顺序返回,但会以相反的顺序返回。我在您的代码中没有看到任何说明使用同步请求的内容……您的注释现在看起来有点像(在此处填入合适的词)。-)啊,我错了。我看到了extend
逻辑,我认为选项正在扩展到opts中。@Quantastical,$。extend
修改第一个参数并返回它,但您没有捕获返回值。Ook。我也是。$。扩展(opts,options)
当然是我的意思。Shame=)现在可以工作了。(因此,警报的顺序在执行顺序中并不总是线性的?无论如何,在FF中…(异步调用就是这样产生的效果:异步事件放在事件队列上;但是当前运行的代码首先完成,然后才处理事件队列,触发回调函数)啊,我错了。我看到了extend
逻辑,我认为选项正在扩展到opts中。@Quantastical,$。extend
修改第一个参数并返回它,但您没有捕获返回值。Ook。我也是。$。扩展(opts,options)
当然是我的意思。Shame=)现在可以工作了。(因此,警报的顺序在执行顺序中并不总是线性的?无论如何,在FF中…(异步调用就是这样产生的效果:异步事件放在事件队列上;但是当前运行的代码首先完成,然后才处理事件队列,触发回调函数)
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);
}