奇怪的Javascript封闭错误

时间:2016-05-12 21:17:54

标签: 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.stringify(result));
    return result;
}

运行时,警告框显示:

  

结果CB:{“成功”:真实,“数据”:“dtrombley”}

(这就是webservice实际返回的内容),然后:

  

结果POST-CB:是

为什么闭包变量的赋值不起作用?我误解了JS闭包是如何工作的吗?

callServiceOptions()相当漫长 - 但它的要点是它调用jQuery的$ .ajax方法,它的最后一个参数选项扩展为某些默认值(在这种情况下,async禁用同步查询),然后执行提供回调。

$ .ajax()是否可能以某种方式执行某些禁用/搞砸闭包的方式(但调用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);
}

这与要求如何从异步事件返回值的任何问题都不重复。我有一个工作callServiceAsync(),它做得很漂亮。我正在使用同步模式,如果你不熟悉它,请接受这个问题的传递......

1 个答案:

答案 0 :(得分:6)

您的功能是异步的。

虽然您创建的对象看起来像{async: false},但您将其作为第4个参数传递给callServiceOptions,因此它会被放置在options变量中。

您只能访问该变量两次(options.successoptions.error),因此async属性从不用于任何内容(因此$.ajax使用默认值{{1 }})。

在您致电true之前添加console.log(opts)会显示此信息。