Jquery异步ajax变量不同步更改

时间:2015-09-01 16:05:52

标签: javascript jquery ajax asynchronous xmlhttprequest

然后这是错误,var的值不会改变。我做错了什么? stackoverflow的更多细节! stackoverflow的更多细节!有关stackoverflow的更多详细信息!

    function set(id, edate)
    {
        var good = true;

        $.post("ajax.php", { func: "set", id: id, edate: edate},
            function(data){
                data = JSON.parse(data);
                if(data.error) {
                    good = false;
                    if(data.emessage=='SqlError') { alert('Ошибка выполнения запроса, перезагрузите страницу и попробуйте снова.'); }
                }
                else {
                    if(data.emessage=='AddOk') { alert('Запись о выданной зарплате успешно создана!'); }
                    else if(data.emessage=='DeleteOk') { alert('Выдача зарплаты ОТМЕНЕНА успешно!'); }
                }
            }
        );

        return good;
    }

1 个答案:

答案 0 :(得分:0)

问题是你有一个异步函数(AJAX POST)来操纵你的变量。 您无法直接返回变量,而是考虑使用以下内容:

function set(id, edate, callback)
    {
        $.post("ajax.php", { func: "set", id: id, edate: edate},
            function(data){
                data = JSON.parse(data);
                if(data.error) {
                    callback(false);
                }else{
                    callback(true);
                }
            }
        );
    }

用法:

set(id, edate, function(good){

});

是什么让$.post异步?

$.post的Jquery来源:

    function (url, data, callback, type) {
        // Shift arguments if data argument was omitted
        if (jQuery.isFunction(data)) {
            type = type || callback;
            callback = data;
            data = undefined;
        }

        // The url can be an options object (which then must have .url)
        return jQuery.ajax(jQuery.extend({
            url: url,
            type: method,
            dataType: type,
            data: data,
            success: callback
        },
        jQuery.isPlainObject(url) && url));
    }

调用JQuery.ajax

function (url, options) {

    // If url is an object, simulate pre-1.5 signature
    if (typeof url === "object") {
        options = url;
        url = undefined;
    }

    // Force options to be an object
    options = options || {};

    var transport,
    // URL without anti-cache param
    cacheURL,
    // Response headers
    responseHeadersString, responseHeaders,
    // timeout handle
    timeoutTimer,
    // Url cleanup var
    urlAnchor,
    // To know if global events are to be dispatched
    fireGlobals,
    // Loop variable
    i,
    // Create the final options object
    s = jQuery.ajaxSetup({},
    options),
    // Callbacks context
    callbackContext = s.context || s,
    // Context for global events is callbackContext if it is a DOM node or jQuery collection
    globalEventContext = s.context && (callbackContext.nodeType || callbackContext.jquery) ? jQuery(callbackContext) : jQuery.event,
    // Deferreds
    deferred = jQuery.Deferred(),
    completeDeferred = jQuery.Callbacks("once memory"),
    // Status-dependent callbacks
    statusCode = s.statusCode || {},
    // Headers (they are sent all at once)
    requestHeaders = {},
    requestHeadersNames = {},
    // The jqXHR state
    state = 0,
    // Default abort message
    strAbort = "canceled",
    // Fake xhr
    jqXHR = {
        readyState: 0,

        // Builds headers hashtable if needed
        getResponseHeader: function (key) {
            var match;
            if (state === 2) {
                if (!responseHeaders) {
                    responseHeaders = {};
                    while ((match = rheaders.exec(responseHeadersString))) {
                        responseHeaders[match[1].toLowerCase()] = match[2];
                    }
                }
                match = responseHeaders[key.toLowerCase()];
            }
            return match == null ? null : match;
        },

        // Raw string
        getAllResponseHeaders: function () {
            return state === 2 ? responseHeadersString : null;
        },

        // Caches the header
        setRequestHeader: function (name, value) {
            var lname = name.toLowerCase();
            if (!state) {
                name = requestHeadersNames[lname] = requestHeadersNames[lname] || name;
                requestHeaders[name] = value;
            }
            return this;
        },

        // Overrides response content-type header
        overrideMimeType: function (type) {
            if (!state) {
                s.mimeType = type;
            }
            return this;
        },

        // Status-dependent callbacks
        statusCode: function (map) {
            var code;
            if (map) {
                if (state < 2) {
                    for (code in map) {
                        // Lazy-add the new callback in a way that preserves old ones
                        statusCode[code] = [statusCode[code], map[code]];
                    }
                } else {
                    // Execute the appropriate callbacks
                    jqXHR.always(map[jqXHR.status]);
                }
            }
            return this;
        },

        // Cancel the request
        abort: function (statusText) {
            var finalText = statusText || strAbort;
            if (transport) {
                transport.abort(finalText);
            }
            done(0, finalText);
            return this;
        }
    };

    // Attach deferreds
    deferred.promise(jqXHR);

    // Remove hash character (#7531: and string promotion)
    // Add protocol if not provided (prefilters might expect it)
    // Handle falsy url in the settings object (#10093: consistency with old signature)
    // We also use the url parameter if available
    s.url = ((url || s.url || location.href) + "").replace(rhash, "").replace(rprotocol, location.protocol + "//");

    // Alias method option to type as per ticket #12004
    s.type = options.method || options.type || s.method || s.type;

    // Extract dataTypes list
    s.dataTypes = jQuery.trim(s.dataType || "*").toLowerCase().match(rnotwhite) || [""];

    // A cross-domain request is in order when the origin doesn't match the current origin.
    if (s.crossDomain == null) {
        urlAnchor = document.createElement("a");

        // Support: IE8-11+
        // IE throws exception if url is malformed, e.g. http://example.com:80x/
        try {
            urlAnchor.href = s.url;
            // Support: IE8-11+
            // Anchor's host property isn't correctly set when s.url is relative
            urlAnchor.href = urlAnchor.href;
            s.crossDomain = originAnchor.protocol + "//" + originAnchor.host !== urlAnchor.protocol + "//" + urlAnchor.host;
        } catch(e) {
            // If there is an error parsing the URL, assume it is crossDomain,
            // it can be rejected by the transport if it is invalid
            s.crossDomain = true;
        }
    }

    // Convert data if not already a string
    if (s.data && s.processData && typeof s.data !== "string") {
        s.data = jQuery.param(s.data, s.traditional);
    }

    // Apply prefilters
    inspectPrefiltersOrTransports(prefilters, s, options, jqXHR);

    // If request was aborted inside a prefilter, stop there
    if (state === 2) {
        return jqXHR;
    }

    // We can fire global events as of now if asked to
    // Don't fire events if jQuery.event is undefined in an AMD-usage scenario (#15118)
    fireGlobals = jQuery.event && s.global;

    // Watch for a new set of requests
    if (fireGlobals && jQuery.active++===0) {
        jQuery.event.trigger("ajaxStart");
    }

    // Uppercase the type
    s.type = s.type.toUpperCase();

    // Determine if request has content
    s.hasContent = !rnoContent.test(s.type);

    // Save the URL in case we're toying with the If-Modified-Since
    // and/or If-None-Match header later on
    cacheURL = s.url;

    // More options handling for requests with no content
    if (!s.hasContent) {

        // If data is available, append data to url
        if (s.data) {
            cacheURL = (s.url += (rquery.test(cacheURL) ? "&" : "?") + s.data);
            // #9682: remove data so that it's not used in an eventual retry
            delete s.data;
        }

        // Add anti-cache in url if needed
        if (s.cache === false) {
            s.url = rts.test(cacheURL) ?

            // If there is already a '_' parameter, set its value
            cacheURL.replace(rts, "$1_=" + nonce++) :

            // Otherwise add one to the end
            cacheURL + (rquery.test(cacheURL) ? "&" : "?") + "_=" + nonce++;
        }
    }

    // Set the If-Modified-Since and/or If-None-Match header, if in ifModified mode.
    if (s.ifModified) {
        if (jQuery.lastModified[cacheURL]) {
            jqXHR.setRequestHeader("If-Modified-Since", jQuery.lastModified[cacheURL]);
        }
        if (jQuery.etag[cacheURL]) {
            jqXHR.setRequestHeader("If-None-Match", jQuery.etag[cacheURL]);
        }
    }

    // Set the correct header, if data is being sent
    if (s.data && s.hasContent && s.contentType !== false || options.contentType) {
        jqXHR.setRequestHeader("Content-Type", s.contentType);
    }

    // Set the Accepts header for the server, depending on the dataType
    jqXHR.setRequestHeader("Accept", s.dataTypes[0] && s.accepts[s.dataTypes[0]] ? s.accepts[s.dataTypes[0]] + (s.dataTypes[0] !== "*" ? ", " + allTypes + "; q=0.01" : "") : s.accepts["*"]);

    // Check for headers option
    for (i in s.headers) {
        jqXHR.setRequestHeader(i, s.headers[i]);
    }

    // Allow custom headers/mimetypes and early abort
    if (s.beforeSend && (s.beforeSend.call(callbackContext, jqXHR, s) === false || state === 2)) {

        // Abort if not done already and return
        return jqXHR.abort();
    }

    // Aborting is no longer a cancellation
    strAbort = "abort";

    // Install callbacks on deferreds
    completeDeferred.add(s.complete);
    jqXHR.done(s.success);
    jqXHR.fail(s.error);

    // Get transport
    transport = inspectPrefiltersOrTransports(transports, s, options, jqXHR);

    // If no transport, we auto-abort
    if (!transport) {
        done(-1, "No Transport");
    } else {
        jqXHR.readyState = 1;

        // Send global event
        if (fireGlobals) {
            globalEventContext.trigger("ajaxSend", [jqXHR, s]);
        }

        // If request was aborted inside ajaxSend, stop there
        if (state === 2) {
            return jqXHR;
        }

        // Timeout
        if (s.async && s.timeout > 0) {
            timeoutTimer = window.setTimeout(function () {
                jqXHR.abort("timeout");
            },
            s.timeout);
        }

        try {
            state = 1;
            transport.send(requestHeaders, done);
        } catch(e) {
            // Propagate exception as error if not done
            if (state < 2) {
                done(-1, e);
                // Simply rethrow otherwise
            } else {
                throw e;
            }
        }
    }

    // Callback for when everything is done


    function done(status, nativeStatusText, responses, headers) {
        var isSuccess, success, error, response, modified, statusText = nativeStatusText;

        // Called once
        if (state === 2) {
            return;
        }

        // State is "done" now
        state = 2;

        // Clear timeout if it exists
        if (timeoutTimer) {
            window.clearTimeout(timeoutTimer);
        }

        // Dereference transport for early garbage collection
        // (no matter how long the jqXHR object will be used)
        transport = undefined;

        // Cache response headers
        responseHeadersString = headers || "";

        // Set readyState
        jqXHR.readyState = status > 0 ? 4 : 0;

        // Determine if successful
        isSuccess = status >= 200 && status < 300 || status === 304;

        // Get response data
        if (responses) {
            response = ajaxHandleResponses(s, jqXHR, responses);
        }

        // Convert no matter what (that way responseXXX fields are always set)
        response = ajaxConvert(s, response, jqXHR, isSuccess);

        // If successful, handle type chaining
        if (isSuccess) {

            // Set the If-Modified-Since and/or If-None-Match header, if in ifModified mode.
            if (s.ifModified) {
                modified = jqXHR.getResponseHeader("Last-Modified");
                if (modified) {
                    jQuery.lastModified[cacheURL] = modified;
                }
                modified = jqXHR.getResponseHeader("etag");
                if (modified) {
                    jQuery.etag[cacheURL] = modified;
                }
            }

            // if no content
            if (status === 204 || s.type === "HEAD") {
                statusText = "nocontent";

                // if not modified
            } else if (status === 304) {
                statusText = "notmodified";

                // If we have data, let's convert it
            } else {
                statusText = response.state;
                success = response.data;
                error = response.error;
                isSuccess = !error;
            }
        } else {
            // Extract error from statusText and normalize for non-aborts
            error = statusText;
            if (status || !statusText) {
                statusText = "error";
                if (status < 0) {
                    status = 0;
                }
            }
        }

        // Set data for the fake xhr object
        jqXHR.status = status;
        jqXHR.statusText = (nativeStatusText || statusText) + "";

        // Success/Error
        if (isSuccess) {
            deferred.resolveWith(callbackContext, [success, statusText, jqXHR]);
        } else {
            deferred.rejectWith(callbackContext, [jqXHR, statusText, error]);
        }

        // Status-dependent callbacks
        jqXHR.statusCode(statusCode);
        statusCode = undefined;

        if (fireGlobals) {
            globalEventContext.trigger(isSuccess ? "ajaxSuccess" : "ajaxError", [jqXHR, s, isSuccess ? success : error]);
        }

        // Complete
        completeDeferred.fireWith(callbackContext, [jqXHR, statusText]);

        if (fireGlobals) {
            globalEventContext.trigger("ajaxComplete", [jqXHR, s]);
            // Handle the global AJAX counter
            if (! (--jQuery.active)) {
                jQuery.event.trigger("ajaxStop");
            }
        }
    }

    return jqXHR;
}

Jquery事件:

$.fn.ajaxStart = function ( handler ) { return this.on('ajaxStart', handler); };
$.fn.ajaxStop = function ( handler ) { return this.on('ajaxStop', handler); };
$.fn.ajaxComplete = function ( handler ) { return this.on('ajaxComplete', handler); };
$.fn.ajaxError = function ( handler ) { return this.on('ajaxError', handler); };
$.fn.ajaxSuccess = function ( handler ) { return this.on('ajaxSuccess', handler); };
$.fn.ajaxSend = function ( handler ) { return this.on('ajaxSend', handler); };

jQuery.ajaxSetup:

function (target, settings) {
    return settings ?

    // Building a settings object
    ajaxExtend(ajaxExtend(target, jQuery.ajaxSettings), settings) :

    // Extending ajaxSettings
    ajaxExtend(jQuery.ajaxSettings, target);
}

jQuery.ajax设置:

{
    "url": "http://james.padolsey.com/jquery/#v=git&fn=",
    "type": "GET",
    "isLocal": false,
    "global": true,
    "processData": true,
    "async": true,
    "contentType": "application/x-www-form-urlencoded; charset=UTF-8",
    "accepts": {
        "*": "*/*",
        "text": "text/plain",
        "html": "text/html",
        "xml": "application/xml, text/xml",
        "json": "application/json, text/javascript",
        "script": "text/javascript, application/javascript, application/ecmascript, application/x-ecmascript"
    },
    "contents": {
        "xml": {},
        "html": {},
        "json": {},
        "script": {}
    },
    "responseFields": {
        "xml": "responseXML",
        "text": "responseText",
        "json": "responseJSON"
    },
    "converters": {
        "text html": true
    },
    "flatOptions": {
        "url": true,
        "context": true
    },
    "jsonp": "callback"
}

XHR:

jQuery.ajaxSettings.xhr = window.ActiveXObject !== undefined ?
    // Support: IE6+
    function() {

        // XHR cannot access local files, always use ActiveX for that case
        return !this.isLocal &&

            // Support: IE7-8
            // oldIE XHR does not support non-RFC2616 methods (#13240)
            // See http://msdn.microsoft.com/en-us/library/ie/ms536648(v=vs.85).aspx
            // and http://www.w3.org/Protocols/rfc2616/rfc2616-sec9.html#sec9
            // Although this check for six methods instead of eight
            // since IE also does not support "trace" and "connect"
            /^(get|post|head|put|delete|options)$/i.test( this.type ) &&

            createStandardXHR() || createActiveXHR();
    } :
    // For all other browsers, use the standard XMLHttpRequest object
    createStandardXHR;

var xhrId = 0,
    xhrCallbacks = {},
    xhrSupported = jQuery.ajaxSettings.xhr();

// Support: IE<10
// Open requests must be manually aborted on unload (#5280)
// See https://support.microsoft.com/kb/2856746 for more info
if ( window.attachEvent ) {
    window.attachEvent( "onunload", function() {
        for ( var key in xhrCallbacks ) {
            xhrCallbacks[ key ]( undefined, true );
        }
    });
}

最终jQuery.ajaxSettings.xhr决定了为与服务器通信创建的对象类型。

  

所有现代浏览器都支持XMLHttpRequest对象(IE5和IE6使用   一个ActiveXObject)。

     

XMLHttpRequest对象用于与服务器交换数据   在幕后。这意味着可以更新a的部分   网页,无需重新加载整个页面。

quoted from

  

&#34;如果您使用扩展程序中的XMLHttpRequest,则应使用它   异步。在这种情况下,您会在数据时收到回调   已收到,这使浏览器继续正常工作   正在处理您的请求。&#34;

您可以使XMLHttpRequest同步,JQUERY允许您这样做( reffer to jquery.ajax.settings [&#34; asyc&#34;] );但是,默认情况下启用asyc。