1

Using variables in ajax callbacks seems to work but I don't understand why. Here is an example. Can someone explain why the variable, in this case subSiteUrl, set outside of the callback is correct?

I would expect the variable to be unreliable as the loop likely progressed prior to the callback occurring.

function getSubWebProjInformation() {
    $.each(subWebsArray, function() {
        var subSiteUrl = this.Url;
        var targetUrl = this.Url + "/_vti_bin/lists.asmx";
        var listName = "Project Information";
        var soapEnv = "<?xml version=\"1.0\" encoding=\"utf-8\"?>" +
            "<soap:Envelope xmlns:xsi=\"http://www.w3.org/2001/XMLSchema-instance\" xmlns:xsd=\"http://www.w3.org/2001/XMLSchema\" xmlns:soap=\"http://schemas.xmlsoap.org/soap/envelope/\">" +
            "   <soap:Body>" +
            "       <GetList xmlns=\"http://schemas.microsoft.com/sharepoint/soap/\">" +
            "            <listName>" + listName + "</listName>" +
            "      </GetList>" +
            "   </soap:Body>" +
            "</soap:Envelope>";
        $.ajax({
            cache: false,
            url: targetUrl,
            type: "POST",
            dataType: "xml",
            data: soapEnv,
            contentType: "text/xml; charset=utf-8",
            beforeSend: function(xhr) {
                xhr.setRequestHeader("SOAPAction", "http://schemas.microsoft.com/sharepoint/soap/GetList");
            },
            complete: function(msg) {
                if (msg.status == 200) {
                    var projFieldsArray = [];
                    $(msg.responseXML).find("Field").each(function() {
                        var staticName = $(this).attr("StaticName");
                        var displayName = $(this).attr("DisplayName");
                        var isFromBaseType = $(this).attr("FromBaseType") === "TRUE";
                        if (!isFromBaseType && staticName && staticName != "PermMask" || staticName === "Title") {
                            var f = {};
                            f.displayName = displayName;
                            f.staticName = staticName;
                            projFieldsArray.push(f);
                        }
                    });
                    updateSubWebObjectWithProjFields(subSiteUrl, projFieldsArray);
                } else {
                    //Failure
                    var errorCode = $(msg.responseXML).find("errorcode").text();
                    var errorString = $(msg.responseXML).find("errorstring").text();
                    if (errorString.length === 0) {
                        errorString = $(msg.responseXML).find("faultstring").text();
                    }
                    errorString = errorString.replace(/(\r\n|\n|\r)/gm, "");
                    showStatusBar("Oh no! " + errorString);
                }
            },
        });
    });
}

function updateSubWebObjectWithProjFields(subSiteUrl, projFieldsArray) {
    console.log(subSiteUrl);
    $.each(projFieldsArray, function() {
        console.log(this.displayName + ": " + this.staticName);
    });
}
Justin Russell
  • 488
  • 2
  • 10

1 Answers1

0

Setting var subSiteUrl = this.Url; will allow the value inside of this.Url to be stored. In javascript variables hold values, not references. So when this changes, the value stored inside of subSiteUrl is still the same value. As a result of this changing though, this.Url will be different.

Saving the value of this or a property of this can be very beneficial. It is a best practice approach to keeping access to scope, and I wrote a canonical answer on it here: Save access to this scope.

I would expect the variable to be unreliable as the loop likely progressed prior to the callback occurring

Two things are happening here, the reliability of the variable, and the loop progression. First, the loop is progressing while the ajax call is made. However, that will not affect the reliability of the variable. The variable is scoped to the previous anonymous function. This scope is termed an "Execution context" and will hold on to the value of the variable until the context is no longer of use.

In summary, storing the variable is a good idea, and perfectly safe to use in the context of your example.

Community
  • 1
  • 1
Travis J
  • 81,153
  • 41
  • 202
  • 273