Warning: file_get_contents(/data/phpspider/zhask/data//catemap/8/grails/5.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
奇怪的Javascript闭包错误_Javascript_Jquery_Ajax_Synchronous - Fatal编程技术网

奇怪的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);
}